opik 1.6.4__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 +33 -2
- 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/__init__.py +5 -0
- opik/api_objects/attachment/attachment.py +20 -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 +220 -0
- opik/api_objects/attachment/converters.py +51 -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/conversation/__init__.py +0 -0
- opik/api_objects/conversation/conversation_factory.py +43 -0
- opik/api_objects/conversation/conversation_thread.py +49 -0
- opik/api_objects/data_helpers.py +79 -0
- opik/api_objects/dataset/dataset.py +107 -45
- opik/api_objects/dataset/rest_operations.py +12 -3
- opik/api_objects/experiment/experiment.py +81 -45
- 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 +88 -19
- opik/api_objects/helpers.py +104 -7
- opik/api_objects/local_recording.py +81 -0
- opik/api_objects/opik_client.py +872 -174
- opik/api_objects/opik_query_language.py +136 -18
- opik/api_objects/optimization/__init__.py +3 -0
- opik/api_objects/optimization/optimization.py +39 -0
- opik/api_objects/prompt/__init__.py +13 -1
- 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 +193 -41
- opik/api_objects/prompt/text/__init__.py +1 -0
- opik/api_objects/prompt/text/prompt.py +174 -0
- opik/api_objects/prompt/text/prompt_template.py +55 -0
- opik/api_objects/prompt/types.py +29 -0
- opik/api_objects/rest_stream_parser.py +98 -0
- opik/api_objects/search_helpers.py +89 -0
- opik/api_objects/span/span_client.py +165 -45
- opik/api_objects/span/span_data.py +136 -25
- opik/api_objects/threads/__init__.py +0 -0
- opik/api_objects/threads/threads_client.py +185 -0
- opik/api_objects/trace/trace_client.py +72 -36
- opik/api_objects/trace/trace_data.py +112 -26
- 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 +62 -4
- opik/configurator/configure.py +45 -6
- opik/configurator/opik_rest_helpers.py +4 -1
- opik/context_storage.py +164 -65
- opik/datetime_helpers.py +12 -0
- opik/decorator/arguments_helpers.py +9 -1
- opik/decorator/base_track_decorator.py +298 -146
- opik/decorator/context_manager/__init__.py +0 -0
- opik/decorator/context_manager/span_context_manager.py +123 -0
- opik/decorator/context_manager/trace_context_manager.py +84 -0
- opik/decorator/generator_wrappers.py +3 -2
- opik/decorator/inspect_helpers.py +11 -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 +49 -21
- opik/decorator/tracker.py +9 -1
- opik/dict_utils.py +3 -3
- opik/environment.py +13 -1
- opik/error_tracking/api.py +1 -1
- opik/error_tracking/before_send.py +6 -5
- opik/error_tracking/environment_details.py +29 -7
- opik/error_tracking/error_filtering/filter_by_response_status_code.py +42 -0
- opik/error_tracking/error_filtering/filter_chain_builder.py +14 -3
- opik/evaluation/__init__.py +14 -2
- opik/evaluation/engine/engine.py +280 -82
- opik/evaluation/engine/evaluation_tasks_executor.py +15 -10
- opik/evaluation/engine/helpers.py +34 -9
- opik/evaluation/engine/metrics_evaluator.py +237 -0
- opik/evaluation/engine/types.py +5 -4
- opik/evaluation/evaluation_result.py +169 -2
- opik/evaluation/evaluator.py +659 -58
- opik/evaluation/metrics/__init__.py +121 -6
- opik/evaluation/metrics/aggregated_metric.py +92 -0
- opik/evaluation/metrics/arguments_helpers.py +15 -21
- opik/evaluation/metrics/arguments_validator.py +38 -0
- opik/evaluation/metrics/base_metric.py +20 -10
- opik/evaluation/metrics/conversation/__init__.py +48 -0
- opik/evaluation/metrics/conversation/conversation_thread_metric.py +79 -0
- opik/evaluation/metrics/conversation/conversation_turns_factory.py +39 -0
- opik/evaluation/metrics/conversation/g_eval_wrappers.py +19 -0
- opik/evaluation/metrics/conversation/helpers.py +84 -0
- 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/llm_judges/conversational_coherence/__init__.py +0 -0
- opik/evaluation/metrics/conversation/llm_judges/conversational_coherence/metric.py +274 -0
- opik/evaluation/metrics/conversation/llm_judges/conversational_coherence/schema.py +16 -0
- opik/evaluation/metrics/conversation/llm_judges/conversational_coherence/templates.py +95 -0
- opik/evaluation/metrics/conversation/llm_judges/g_eval_wrappers.py +442 -0
- opik/evaluation/metrics/conversation/llm_judges/session_completeness/__init__.py +0 -0
- opik/evaluation/metrics/conversation/llm_judges/session_completeness/metric.py +295 -0
- opik/evaluation/metrics/conversation/llm_judges/session_completeness/schema.py +22 -0
- opik/evaluation/metrics/conversation/llm_judges/session_completeness/templates.py +139 -0
- opik/evaluation/metrics/conversation/llm_judges/user_frustration/__init__.py +0 -0
- opik/evaluation/metrics/conversation/llm_judges/user_frustration/metric.py +277 -0
- opik/evaluation/metrics/conversation/llm_judges/user_frustration/schema.py +16 -0
- opik/evaluation/metrics/conversation/llm_judges/user_frustration/templates.py +135 -0
- opik/evaluation/metrics/conversation/types.py +34 -0
- opik/evaluation/metrics/conversation_types.py +9 -0
- opik/evaluation/metrics/heuristics/bertscore.py +107 -0
- opik/evaluation/metrics/heuristics/bleu.py +43 -16
- opik/evaluation/metrics/heuristics/chrf.py +127 -0
- opik/evaluation/metrics/heuristics/contains.py +50 -11
- opik/evaluation/metrics/heuristics/distribution_metrics.py +331 -0
- opik/evaluation/metrics/heuristics/equals.py +4 -1
- opik/evaluation/metrics/heuristics/gleu.py +113 -0
- opik/evaluation/metrics/heuristics/is_json.py +9 -3
- opik/evaluation/metrics/heuristics/language_adherence.py +123 -0
- opik/evaluation/metrics/heuristics/levenshtein_ratio.py +6 -5
- 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/regex_match.py +4 -1
- opik/evaluation/metrics/heuristics/rouge.py +148 -0
- opik/evaluation/metrics/heuristics/sentiment.py +98 -0
- 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 +27 -30
- opik/evaluation/metrics/llm_judges/answer_relevance/parser.py +27 -0
- opik/evaluation/metrics/llm_judges/answer_relevance/templates.py +10 -10
- opik/evaluation/metrics/llm_judges/context_precision/metric.py +28 -31
- opik/evaluation/metrics/llm_judges/context_precision/parser.py +27 -0
- opik/evaluation/metrics/llm_judges/context_precision/template.py +7 -7
- opik/evaluation/metrics/llm_judges/context_recall/metric.py +27 -31
- opik/evaluation/metrics/llm_judges/context_recall/parser.py +27 -0
- opik/evaluation/metrics/llm_judges/context_recall/template.py +7 -7
- opik/evaluation/metrics/llm_judges/factuality/metric.py +7 -26
- opik/evaluation/metrics/llm_judges/factuality/parser.py +35 -0
- opik/evaluation/metrics/llm_judges/factuality/template.py +1 -1
- opik/evaluation/metrics/llm_judges/g_eval/__init__.py +5 -0
- opik/evaluation/metrics/llm_judges/g_eval/metric.py +244 -113
- opik/evaluation/metrics/llm_judges/g_eval/parser.py +161 -0
- 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 +23 -27
- opik/evaluation/metrics/llm_judges/hallucination/parser.py +29 -0
- opik/evaluation/metrics/llm_judges/hallucination/template.py +2 -4
- 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 +23 -28
- opik/evaluation/metrics/llm_judges/moderation/parser.py +27 -0
- opik/evaluation/metrics/llm_judges/moderation/template.py +2 -2
- opik/evaluation/metrics/llm_judges/parsing_helpers.py +26 -0
- 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/__init__.py +3 -0
- opik/evaluation/metrics/llm_judges/trajectory_accuracy/metric.py +171 -0
- opik/evaluation/metrics/llm_judges/trajectory_accuracy/parser.py +38 -0
- opik/evaluation/metrics/llm_judges/trajectory_accuracy/templates.py +65 -0
- opik/evaluation/metrics/llm_judges/usefulness/metric.py +23 -32
- opik/evaluation/metrics/llm_judges/usefulness/parser.py +28 -0
- opik/evaluation/metrics/ragas_metric.py +112 -0
- opik/evaluation/models/__init__.py +10 -0
- opik/evaluation/models/base_model.py +140 -18
- opik/evaluation/models/langchain/__init__.py +3 -0
- opik/evaluation/models/langchain/langchain_chat_model.py +166 -0
- opik/evaluation/models/langchain/message_converters.py +106 -0
- opik/evaluation/models/langchain/opik_monitoring.py +23 -0
- opik/evaluation/models/litellm/litellm_chat_model.py +186 -40
- opik/evaluation/models/litellm/opik_monitor.py +24 -21
- 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/__init__.py +0 -0
- opik/evaluation/threads/context_helper.py +32 -0
- opik/evaluation/threads/evaluation_engine.py +181 -0
- opik/evaluation/threads/evaluation_result.py +18 -0
- opik/evaluation/threads/evaluator.py +120 -0
- opik/evaluation/threads/helpers.py +51 -0
- opik/evaluation/types.py +9 -1
- opik/exceptions.py +116 -3
- opik/file_upload/__init__.py +0 -0
- opik/file_upload/base_upload_manager.py +39 -0
- opik/file_upload/file_upload_monitor.py +14 -0
- opik/file_upload/file_uploader.py +141 -0
- opik/file_upload/mime_type.py +9 -0
- opik/file_upload/s3_multipart_upload/__init__.py +0 -0
- opik/file_upload/s3_multipart_upload/file_parts_strategy.py +89 -0
- opik/file_upload/s3_multipart_upload/s3_file_uploader.py +86 -0
- opik/file_upload/s3_multipart_upload/s3_upload_error.py +29 -0
- opik/file_upload/thread_pool.py +17 -0
- opik/file_upload/upload_client.py +114 -0
- opik/file_upload/upload_manager.py +255 -0
- opik/file_upload/upload_options.py +37 -0
- opik/format_helpers.py +17 -0
- opik/guardrails/__init__.py +4 -0
- opik/guardrails/guardrail.py +157 -0
- opik/guardrails/guards/__init__.py +5 -0
- opik/guardrails/guards/guard.py +17 -0
- opik/guardrails/guards/pii.py +47 -0
- opik/guardrails/guards/topic.py +76 -0
- opik/guardrails/rest_api_client.py +34 -0
- opik/guardrails/schemas.py +24 -0
- opik/guardrails/tracing.py +61 -0
- opik/healthcheck/__init__.py +2 -1
- opik/healthcheck/checks.py +2 -2
- opik/healthcheck/rich_representation.py +1 -1
- 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 +75 -4
- opik/id_helpers.py +18 -0
- opik/integrations/adk/__init__.py +14 -0
- opik/integrations/adk/callback_context_info_extractors.py +32 -0
- opik/integrations/adk/graph/__init__.py +0 -0
- opik/integrations/adk/graph/mermaid_graph_builder.py +128 -0
- opik/integrations/adk/graph/nodes.py +101 -0
- opik/integrations/adk/graph/subgraph_edges_builders.py +41 -0
- opik/integrations/adk/helpers.py +48 -0
- opik/integrations/adk/legacy_opik_tracer.py +381 -0
- opik/integrations/adk/opik_tracer.py +370 -0
- opik/integrations/adk/patchers/__init__.py +4 -0
- opik/integrations/adk/patchers/adk_otel_tracer/__init__.py +0 -0
- opik/integrations/adk/patchers/adk_otel_tracer/llm_span_helpers.py +30 -0
- opik/integrations/adk/patchers/adk_otel_tracer/opik_adk_otel_tracer.py +201 -0
- opik/integrations/adk/patchers/litellm_wrappers.py +91 -0
- opik/integrations/adk/patchers/llm_response_wrapper.py +105 -0
- opik/integrations/adk/patchers/patchers.py +64 -0
- opik/integrations/adk/recursive_callback_injector.py +126 -0
- opik/integrations/aisuite/aisuite_decorator.py +8 -3
- opik/integrations/aisuite/opik_tracker.py +1 -0
- opik/integrations/anthropic/messages_create_decorator.py +8 -3
- opik/integrations/anthropic/opik_tracker.py +0 -1
- 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} +18 -8
- opik/integrations/bedrock/invoke_agent_decorator.py +12 -7
- 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 +43 -4
- opik/integrations/bedrock/types.py +19 -0
- opik/integrations/crewai/crewai_decorator.py +34 -56
- 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 +246 -84
- opik/integrations/dspy/graph.py +88 -0
- opik/integrations/dspy/parsers.py +168 -0
- opik/integrations/genai/encoder_extension.py +2 -6
- opik/integrations/genai/generate_content_decorator.py +20 -13
- opik/integrations/guardrails/guardrails_decorator.py +4 -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/constants.py +35 -0
- opik/integrations/haystack/converters.py +1 -2
- opik/integrations/haystack/opik_connector.py +28 -6
- opik/integrations/haystack/opik_span_bridge.py +284 -0
- opik/integrations/haystack/opik_tracer.py +124 -222
- 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 +2 -2
- opik/integrations/langchain/opik_tracer.py +641 -206
- opik/integrations/langchain/provider_usage_extractors/__init__.py +5 -0
- opik/integrations/langchain/provider_usage_extractors/anthropic_usage_extractor.py +101 -0
- opik/integrations/langchain/provider_usage_extractors/anthropic_vertexai_usage_extractor.py +67 -0
- opik/integrations/langchain/provider_usage_extractors/bedrock_usage_extractor.py +94 -0
- opik/integrations/langchain/provider_usage_extractors/google_generative_ai_usage_extractor.py +109 -0
- opik/integrations/langchain/provider_usage_extractors/groq_usage_extractor.py +92 -0
- opik/integrations/langchain/provider_usage_extractors/langchain_run_helpers/__init__.py +15 -0
- opik/integrations/langchain/provider_usage_extractors/langchain_run_helpers/helpers.py +134 -0
- opik/integrations/langchain/provider_usage_extractors/langchain_run_helpers/langchain_usage.py +163 -0
- opik/integrations/langchain/provider_usage_extractors/openai_usage_extractor.py +124 -0
- opik/integrations/langchain/provider_usage_extractors/provider_usage_extractor_protocol.py +29 -0
- opik/integrations/langchain/provider_usage_extractors/usage_extractor.py +48 -0
- opik/integrations/langchain/provider_usage_extractors/vertexai_usage_extractor.py +109 -0
- 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 +179 -78
- opik/integrations/llama_index/event_parsing_utils.py +29 -9
- opik/integrations/openai/agents/opik_tracing_processor.py +204 -32
- opik/integrations/openai/agents/span_data_parsers.py +15 -6
- opik/integrations/openai/chat_completion_chunks_aggregator.py +1 -1
- opik/integrations/openai/{openai_decorator.py → openai_chat_completions_decorator.py} +45 -35
- opik/integrations/openai/openai_responses_decorator.py +158 -0
- opik/integrations/openai/opik_tracker.py +94 -13
- opik/integrations/openai/response_events_aggregator.py +36 -0
- opik/integrations/openai/stream_patchers.py +125 -15
- opik/integrations/sagemaker/auth.py +5 -1
- opik/jsonable_encoder.py +29 -1
- opik/llm_usage/base_original_provider_usage.py +15 -8
- opik/llm_usage/bedrock_usage.py +8 -2
- opik/llm_usage/google_usage.py +6 -1
- opik/llm_usage/llm_usage_info.py +6 -0
- opik/llm_usage/{openai_usage.py → openai_chat_completions_usage.py} +2 -12
- opik/llm_usage/{openai_agent_usage.py → openai_responses_usage.py} +7 -15
- opik/llm_usage/opik_usage.py +36 -10
- opik/llm_usage/opik_usage_factory.py +35 -19
- opik/logging_messages.py +19 -7
- opik/message_processing/arguments_utils.py +22 -0
- opik/message_processing/batching/base_batcher.py +45 -17
- opik/message_processing/batching/batch_manager.py +22 -10
- opik/message_processing/batching/batch_manager_constuctors.py +36 -11
- opik/message_processing/batching/batchers.py +167 -44
- opik/message_processing/batching/flushing_thread.py +0 -3
- opik/message_processing/batching/sequence_splitter.py +50 -5
- 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/message_queue.py +79 -0
- opik/message_processing/messages.py +154 -12
- 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/processors/online_message_processor.py +324 -0
- opik/message_processing/queue_consumer.py +61 -13
- opik/message_processing/streamer.py +102 -31
- opik/message_processing/streamer_constructors.py +67 -12
- opik/opik_context.py +103 -11
- opik/plugins/pytest/decorator.py +2 -2
- opik/plugins/pytest/experiment_runner.py +3 -2
- opik/plugins/pytest/hooks.py +6 -4
- opik/rate_limit/__init__.py +0 -0
- opik/rate_limit/rate_limit.py +25 -0
- opik/rest_api/__init__.py +643 -11
- 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/attachments/__init__.py +17 -0
- opik/rest_api/attachments/client.py +752 -0
- opik/rest_api/attachments/raw_client.py +1125 -0
- opik/rest_api/attachments/types/__init__.py +15 -0
- opik/rest_api/attachments/types/attachment_list_request_entity_type.py +5 -0
- opik/rest_api/attachments/types/download_attachment_request_entity_type.py +5 -0
- opik/rest_api/attachments/types/start_multipart_upload_request_entity_type.py +5 -0
- opik/rest_api/attachments/types/upload_attachment_request_entity_type.py +5 -0
- opik/rest_api/automation_rule_evaluators/__init__.py +2 -0
- opik/rest_api/automation_rule_evaluators/client.py +182 -1162
- opik/rest_api/automation_rule_evaluators/raw_client.py +598 -0
- opik/rest_api/chat_completions/__init__.py +2 -0
- opik/rest_api/chat_completions/client.py +115 -149
- opik/rest_api/chat_completions/raw_client.py +339 -0
- opik/rest_api/check/__init__.py +2 -0
- opik/rest_api/check/client.py +88 -106
- opik/rest_api/check/raw_client.py +258 -0
- opik/rest_api/client.py +112 -212
- opik/rest_api/core/__init__.py +5 -0
- opik/rest_api/core/api_error.py +12 -6
- opik/rest_api/core/client_wrapper.py +4 -14
- opik/rest_api/core/datetime_utils.py +1 -3
- opik/rest_api/core/file.py +2 -5
- opik/rest_api/core/http_client.py +42 -120
- opik/rest_api/core/http_response.py +55 -0
- opik/rest_api/core/jsonable_encoder.py +1 -4
- opik/rest_api/core/pydantic_utilities.py +79 -147
- opik/rest_api/core/query_encoder.py +1 -3
- opik/rest_api/core/serialization.py +10 -10
- 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/__init__.py +5 -0
- opik/rest_api/datasets/client.py +1638 -1091
- opik/rest_api/datasets/raw_client.py +3389 -0
- opik/rest_api/datasets/types/__init__.py +8 -0
- opik/rest_api/datasets/types/dataset_update_visibility.py +5 -0
- opik/rest_api/datasets/types/dataset_write_visibility.py +5 -0
- opik/rest_api/errors/__init__.py +2 -0
- opik/rest_api/errors/bad_request_error.py +4 -3
- opik/rest_api/errors/conflict_error.py +4 -3
- opik/rest_api/errors/forbidden_error.py +4 -2
- opik/rest_api/errors/not_found_error.py +4 -3
- opik/rest_api/errors/not_implemented_error.py +4 -3
- opik/rest_api/errors/unauthorized_error.py +4 -3
- opik/rest_api/errors/unprocessable_entity_error.py +4 -3
- opik/rest_api/experiments/__init__.py +5 -0
- opik/rest_api/experiments/client.py +676 -752
- opik/rest_api/experiments/raw_client.py +1872 -0
- opik/rest_api/experiments/types/__init__.py +10 -0
- 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/experiments/types/experiment_write_type.py +5 -0
- opik/rest_api/feedback_definitions/__init__.py +2 -0
- opik/rest_api/feedback_definitions/client.py +96 -370
- opik/rest_api/feedback_definitions/raw_client.py +541 -0
- opik/rest_api/feedback_definitions/types/__init__.py +2 -0
- opik/rest_api/feedback_definitions/types/find_feedback_definitions_request_type.py +1 -3
- opik/rest_api/guardrails/__init__.py +4 -0
- opik/rest_api/guardrails/client.py +104 -0
- opik/rest_api/guardrails/raw_client.py +102 -0
- opik/rest_api/llm_provider_key/__init__.py +2 -0
- opik/rest_api/llm_provider_key/client.py +166 -440
- opik/rest_api/llm_provider_key/raw_client.py +643 -0
- opik/rest_api/llm_provider_key/types/__init__.py +2 -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/open_telemetry_ingestion/__init__.py +2 -0
- opik/rest_api/open_telemetry_ingestion/client.py +38 -63
- opik/rest_api/open_telemetry_ingestion/raw_client.py +88 -0
- opik/rest_api/optimizations/__init__.py +7 -0
- opik/rest_api/optimizations/client.py +704 -0
- opik/rest_api/optimizations/raw_client.py +920 -0
- opik/rest_api/optimizations/types/__init__.py +7 -0
- opik/rest_api/optimizations/types/optimization_update_status.py +7 -0
- opik/rest_api/projects/__init__.py +10 -1
- opik/rest_api/projects/client.py +180 -855
- opik/rest_api/projects/raw_client.py +1216 -0
- opik/rest_api/projects/types/__init__.py +11 -4
- opik/rest_api/projects/types/project_metric_request_public_interval.py +1 -3
- opik/rest_api/projects/types/project_metric_request_public_metric_type.py +11 -1
- opik/rest_api/projects/types/project_update_visibility.py +5 -0
- opik/rest_api/projects/types/project_write_visibility.py +5 -0
- opik/rest_api/prompts/__init__.py +4 -2
- opik/rest_api/prompts/client.py +381 -970
- opik/rest_api/prompts/raw_client.py +1634 -0
- opik/rest_api/prompts/types/__init__.py +5 -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/raw_client.py +156 -0
- opik/rest_api/redirect/__init__.py +4 -0
- opik/rest_api/redirect/client.py +375 -0
- opik/rest_api/redirect/raw_client.py +566 -0
- opik/rest_api/service_toggles/__init__.py +4 -0
- opik/rest_api/service_toggles/client.py +91 -0
- opik/rest_api/service_toggles/raw_client.py +93 -0
- opik/rest_api/spans/__init__.py +2 -0
- opik/rest_api/spans/client.py +659 -1354
- opik/rest_api/spans/raw_client.py +2383 -0
- opik/rest_api/spans/types/__init__.py +2 -0
- opik/rest_api/spans/types/find_feedback_score_names_1_request_type.py +1 -3
- opik/rest_api/spans/types/get_span_stats_request_type.py +1 -3
- opik/rest_api/spans/types/get_spans_by_project_request_type.py +1 -3
- opik/rest_api/spans/types/span_search_stream_request_public_type.py +1 -3
- opik/rest_api/system_usage/__init__.py +2 -0
- opik/rest_api/system_usage/client.py +157 -216
- opik/rest_api/system_usage/raw_client.py +455 -0
- opik/rest_api/traces/__init__.py +2 -0
- opik/rest_api/traces/client.py +2102 -1625
- opik/rest_api/traces/raw_client.py +4144 -0
- opik/rest_api/types/__init__.py +629 -24
- opik/rest_api/types/aggregation_data.py +27 -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/{json_schema_element.py → annotation_queue_item_ids.py} +5 -7
- 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/{workspace_metadata.py → annotation_queue_reviewer.py} +6 -7
- 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/assistant_message.py +7 -8
- opik/rest_api/types/assistant_message_role.py +1 -3
- opik/rest_api/types/attachment.py +22 -0
- opik/rest_api/types/attachment_page.py +28 -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 +160 -0
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge_public.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge_write.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_object_object_public.py +155 -0
- opik/rest_api/types/automation_rule_evaluator_page_public.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_public.py +155 -0
- 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 +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge_public.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge_write.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python_public.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python_write.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_update.py +143 -0
- opik/rest_api/types/automation_rule_evaluator_update_llm_as_judge.py +6 -6
- 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 +22 -0
- opik/rest_api/types/automation_rule_evaluator_update_trace_thread_user_defined_metric_python.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_update_user_defined_metric_python.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python_public.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python_write.py +6 -6
- opik/rest_api/types/automation_rule_evaluator_write.py +143 -0
- opik/rest_api/types/avg_value_stat_public.py +3 -5
- opik/rest_api/types/batch_delete.py +3 -5
- opik/rest_api/types/batch_delete_by_project.py +20 -0
- opik/rest_api/types/bi_information.py +3 -5
- opik/rest_api/types/bi_information_response.py +4 -6
- 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/categorical_feedback_definition.py +5 -7
- opik/rest_api/types/categorical_feedback_definition_create.py +4 -6
- opik/rest_api/types/categorical_feedback_definition_public.py +5 -7
- opik/rest_api/types/categorical_feedback_definition_update.py +4 -6
- opik/rest_api/types/categorical_feedback_detail.py +3 -5
- opik/rest_api/types/categorical_feedback_detail_create.py +3 -5
- opik/rest_api/types/categorical_feedback_detail_public.py +3 -5
- opik/rest_api/types/categorical_feedback_detail_update.py +3 -5
- opik/rest_api/types/chat_completion_choice.py +4 -6
- opik/rest_api/types/chat_completion_response.py +5 -6
- opik/rest_api/types/check.py +22 -0
- opik/rest_api/types/{json_node_compare.py → check_name.py} +1 -1
- opik/rest_api/types/check_public.py +22 -0
- opik/rest_api/types/check_public_name.py +5 -0
- opik/rest_api/types/check_public_result.py +5 -0
- opik/rest_api/types/check_result.py +5 -0
- opik/rest_api/types/chunked_output_json_node.py +4 -6
- opik/rest_api/types/chunked_output_json_node_public.py +4 -6
- opik/rest_api/types/chunked_output_json_node_public_type.py +6 -10
- opik/rest_api/types/chunked_output_json_node_type.py +6 -10
- opik/rest_api/types/column.py +8 -10
- opik/rest_api/types/column_compare.py +8 -10
- opik/rest_api/types/column_public.py +8 -10
- opik/rest_api/types/column_types_item.py +1 -3
- opik/rest_api/types/comment.py +4 -6
- opik/rest_api/types/comment_compare.py +4 -6
- opik/rest_api/types/comment_public.py +4 -6
- opik/rest_api/types/complete_multipart_upload_request.py +33 -0
- opik/rest_api/types/complete_multipart_upload_request_entity_type.py +5 -0
- opik/rest_api/types/completion_tokens_details.py +3 -5
- opik/rest_api/types/count_value_stat_public.py +3 -5
- opik/rest_api/types/dashboard_page_public.py +24 -0
- opik/rest_api/types/dashboard_public.py +30 -0
- opik/rest_api/types/data_point_double.py +21 -0
- opik/rest_api/types/data_point_number_public.py +3 -5
- opik/rest_api/types/dataset.py +14 -6
- 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 +9 -8
- opik/rest_api/types/dataset_item_batch.py +3 -5
- opik/rest_api/types/dataset_item_changes_public.py +5 -0
- opik/rest_api/types/dataset_item_compare.py +9 -8
- opik/rest_api/types/dataset_item_compare_source.py +1 -3
- 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 +10 -7
- opik/rest_api/types/dataset_item_page_public.py +10 -7
- opik/rest_api/types/dataset_item_public.py +9 -8
- opik/rest_api/types/dataset_item_public_source.py +1 -3
- opik/rest_api/types/dataset_item_source.py +1 -3
- opik/rest_api/types/dataset_item_update.py +39 -0
- opik/rest_api/types/dataset_item_write.py +5 -6
- opik/rest_api/types/dataset_item_write_source.py +1 -3
- opik/rest_api/types/dataset_page_public.py +9 -6
- opik/rest_api/types/dataset_public.py +14 -6
- opik/rest_api/types/dataset_public_status.py +5 -0
- opik/rest_api/types/dataset_public_visibility.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/dataset_visibility.py +5 -0
- opik/rest_api/types/delete_attachments_request.py +23 -0
- opik/rest_api/types/delete_attachments_request_entity_type.py +5 -0
- opik/rest_api/types/delete_feedback_score.py +4 -5
- opik/rest_api/types/delete_ids_holder.py +19 -0
- opik/rest_api/types/delta.py +7 -9
- opik/rest_api/types/error_count_with_deviation.py +21 -0
- opik/rest_api/types/error_count_with_deviation_detailed.py +21 -0
- opik/rest_api/types/error_info.py +3 -5
- opik/rest_api/types/error_info_experiment_item_bulk_write_view.py +21 -0
- opik/rest_api/types/error_info_public.py +3 -5
- opik/rest_api/types/error_info_write.py +3 -5
- opik/rest_api/types/error_message.py +3 -5
- opik/rest_api/types/error_message_detail.py +3 -5
- opik/rest_api/types/error_message_detailed.py +3 -5
- opik/rest_api/types/error_message_public.py +3 -5
- opik/rest_api/types/experiment.py +21 -10
- opik/rest_api/types/experiment_group_aggregations_response.py +20 -0
- opik/rest_api/types/experiment_group_response.py +22 -0
- opik/rest_api/types/experiment_item.py +14 -11
- opik/rest_api/types/experiment_item_bulk_record.py +27 -0
- opik/rest_api/types/experiment_item_bulk_record_experiment_item_bulk_write_view.py +27 -0
- opik/rest_api/types/experiment_item_bulk_upload.py +27 -0
- opik/rest_api/types/experiment_item_compare.py +14 -11
- opik/rest_api/types/experiment_item_compare_trace_visibility_mode.py +5 -0
- opik/rest_api/types/experiment_item_public.py +6 -6
- opik/rest_api/types/experiment_item_public_trace_visibility_mode.py +5 -0
- opik/rest_api/types/experiment_item_trace_visibility_mode.py +5 -0
- opik/rest_api/types/experiment_page_public.py +9 -6
- opik/rest_api/types/experiment_public.py +21 -10
- opik/rest_api/types/experiment_public_status.py +5 -0
- opik/rest_api/types/experiment_public_type.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/experiment_type.py +5 -0
- opik/rest_api/types/export_trace_service_request.py +5 -0
- opik/rest_api/types/feedback.py +40 -27
- opik/rest_api/types/feedback_create.py +27 -13
- opik/rest_api/types/feedback_definition_page_public.py +4 -6
- opik/rest_api/types/feedback_object_public.py +40 -27
- opik/rest_api/types/feedback_public.py +40 -27
- opik/rest_api/types/feedback_score.py +7 -7
- opik/rest_api/types/feedback_score_average.py +3 -5
- opik/rest_api/types/feedback_score_average_detailed.py +3 -5
- opik/rest_api/types/feedback_score_average_public.py +3 -5
- opik/rest_api/types/feedback_score_batch.py +4 -6
- opik/rest_api/types/feedback_score_batch_item.py +6 -6
- opik/rest_api/types/feedback_score_batch_item_source.py +1 -3
- opik/rest_api/types/feedback_score_batch_item_thread.py +32 -0
- opik/rest_api/types/feedback_score_batch_item_thread_source.py +5 -0
- opik/rest_api/types/feedback_score_compare.py +7 -7
- opik/rest_api/types/feedback_score_compare_source.py +1 -3
- opik/rest_api/types/feedback_score_experiment_item_bulk_write_view.py +31 -0
- opik/rest_api/types/feedback_score_experiment_item_bulk_write_view_source.py +5 -0
- opik/rest_api/types/feedback_score_names.py +4 -6
- opik/rest_api/types/feedback_score_public.py +11 -7
- opik/rest_api/types/feedback_score_public_source.py +1 -3
- opik/rest_api/types/feedback_score_source.py +1 -3
- opik/rest_api/types/feedback_update.py +27 -13
- opik/rest_api/types/function.py +4 -7
- opik/rest_api/types/function_call.py +3 -5
- opik/rest_api/types/group_content.py +19 -0
- opik/rest_api/types/group_content_with_aggregations.py +21 -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 +34 -0
- opik/rest_api/types/guardrail_batch.py +20 -0
- opik/rest_api/types/guardrail_name.py +5 -0
- opik/rest_api/types/guardrail_result.py +5 -0
- opik/rest_api/types/guardrail_write.py +33 -0
- opik/rest_api/types/guardrail_write_name.py +5 -0
- opik/rest_api/types/guardrail_write_result.py +5 -0
- opik/rest_api/types/guardrails_validation.py +21 -0
- opik/rest_api/types/guardrails_validation_public.py +21 -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/json_list_string.py +7 -0
- opik/rest_api/types/json_list_string_compare.py +7 -0
- opik/rest_api/types/json_list_string_experiment_item_bulk_write_view.py +7 -0
- opik/rest_api/types/json_list_string_public.py +7 -0
- opik/rest_api/types/json_list_string_write.py +7 -0
- opik/rest_api/types/json_schema.py +5 -8
- opik/rest_api/types/llm_as_judge_code.py +8 -12
- opik/rest_api/types/llm_as_judge_code_public.py +8 -12
- opik/rest_api/types/llm_as_judge_code_write.py +8 -12
- opik/rest_api/types/llm_as_judge_message.py +9 -7
- 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 +9 -7
- opik/rest_api/types/llm_as_judge_message_public_role.py +1 -1
- opik/rest_api/types/llm_as_judge_message_role.py +1 -1
- opik/rest_api/types/llm_as_judge_message_write.py +9 -7
- opik/rest_api/types/llm_as_judge_message_write_role.py +1 -1
- opik/rest_api/types/llm_as_judge_model_parameters.py +6 -5
- opik/rest_api/types/llm_as_judge_model_parameters_public.py +6 -5
- opik/rest_api/types/llm_as_judge_model_parameters_write.py +6 -5
- opik/rest_api/types/llm_as_judge_output_schema.py +4 -6
- opik/rest_api/types/llm_as_judge_output_schema_public.py +4 -6
- opik/rest_api/types/llm_as_judge_output_schema_public_type.py +1 -3
- opik/rest_api/types/llm_as_judge_output_schema_type.py +1 -3
- opik/rest_api/types/llm_as_judge_output_schema_write.py +4 -6
- opik/rest_api/types/llm_as_judge_output_schema_write_type.py +1 -3
- opik/rest_api/types/log_item.py +5 -7
- opik/rest_api/types/log_item_level.py +1 -3
- opik/rest_api/types/log_page.py +4 -6
- 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/multipart_upload_part.py +20 -0
- opik/rest_api/types/numerical_feedback_definition.py +5 -7
- opik/rest_api/types/numerical_feedback_definition_create.py +4 -6
- opik/rest_api/types/numerical_feedback_definition_public.py +5 -7
- opik/rest_api/types/numerical_feedback_definition_update.py +4 -6
- opik/rest_api/types/numerical_feedback_detail.py +3 -5
- opik/rest_api/types/numerical_feedback_detail_create.py +3 -5
- opik/rest_api/types/numerical_feedback_detail_public.py +3 -5
- opik/rest_api/types/numerical_feedback_detail_update.py +3 -5
- opik/rest_api/types/optimization.py +37 -0
- opik/rest_api/types/optimization_page_public.py +28 -0
- opik/rest_api/types/optimization_public.py +37 -0
- opik/rest_api/types/optimization_public_status.py +7 -0
- opik/rest_api/types/optimization_status.py +7 -0
- 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 +30 -0
- opik/rest_api/types/optimization_write_status.py +7 -0
- opik/rest_api/types/page_columns.py +4 -6
- opik/rest_api/types/percentage_value_stat_public.py +4 -6
- opik/rest_api/types/percentage_values.py +8 -16
- opik/rest_api/types/percentage_values_detailed.py +8 -16
- opik/rest_api/types/percentage_values_public.py +8 -16
- opik/rest_api/types/project.py +12 -7
- opik/rest_api/types/project_detailed.py +12 -7
- opik/rest_api/types/project_detailed_visibility.py +5 -0
- opik/rest_api/types/project_metric_response_public.py +5 -9
- opik/rest_api/types/project_metric_response_public_interval.py +1 -3
- opik/rest_api/types/project_metric_response_public_metric_type.py +11 -1
- opik/rest_api/types/project_page_public.py +8 -10
- opik/rest_api/types/project_public.py +6 -6
- opik/rest_api/types/project_public_visibility.py +5 -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_stat_item_object_public.py +8 -17
- opik/rest_api/types/project_stats_public.py +4 -6
- opik/rest_api/types/project_stats_summary.py +4 -6
- opik/rest_api/types/project_stats_summary_item.py +9 -6
- opik/rest_api/types/project_visibility.py +5 -0
- opik/rest_api/types/prompt.py +12 -7
- opik/rest_api/types/prompt_detail.py +12 -7
- opik/rest_api/types/prompt_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_page_public.py +9 -6
- opik/rest_api/types/prompt_public.py +11 -6
- 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_tokens_details.py +19 -0
- opik/rest_api/types/prompt_version.py +7 -6
- opik/rest_api/types/prompt_version_detail.py +7 -6
- opik/rest_api/types/prompt_version_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_link.py +4 -5
- opik/rest_api/types/prompt_version_link_public.py +4 -5
- opik/rest_api/types/prompt_version_link_write.py +3 -5
- opik/rest_api/types/prompt_version_page_public.py +9 -6
- opik/rest_api/types/prompt_version_public.py +7 -6
- 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 +18 -8
- opik/rest_api/types/provider_api_key_page_public.py +27 -0
- opik/rest_api/types/provider_api_key_provider.py +1 -1
- opik/rest_api/types/provider_api_key_public.py +18 -8
- opik/rest_api/types/provider_api_key_public_provider.py +1 -1
- opik/rest_api/types/response_format.py +5 -7
- opik/rest_api/types/response_format_type.py +1 -3
- opik/rest_api/types/result.py +21 -0
- opik/rest_api/types/results_number_public.py +4 -6
- opik/rest_api/types/score_name.py +4 -5
- opik/rest_api/types/service_toggles_config.py +44 -0
- opik/rest_api/types/span.py +13 -15
- opik/rest_api/types/span_batch.py +4 -6
- opik/rest_api/types/span_enrichment_options.py +31 -0
- opik/rest_api/types/span_experiment_item_bulk_write_view.py +39 -0
- opik/rest_api/types/span_experiment_item_bulk_write_view_type.py +5 -0
- 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_public.py +4 -6
- opik/rest_api/types/span_filter_public_operator.py +2 -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_page_public.py +9 -6
- opik/rest_api/types/span_public.py +19 -16
- opik/rest_api/types/span_public_type.py +1 -1
- opik/rest_api/types/span_type.py +1 -1
- opik/rest_api/types/span_update.py +46 -0
- opik/rest_api/types/span_update_type.py +5 -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 +13 -14
- opik/rest_api/types/span_write_type.py +1 -1
- opik/rest_api/types/spans_count_response.py +20 -0
- opik/rest_api/types/start_multipart_upload_response.py +20 -0
- opik/rest_api/types/stream_options.py +3 -5
- 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/tool.py +4 -6
- opik/rest_api/types/tool_call.py +4 -6
- opik/rest_api/types/trace.py +26 -12
- opik/rest_api/types/trace_batch.py +4 -6
- opik/rest_api/types/trace_count_response.py +4 -6
- opik/rest_api/types/trace_enrichment_options.py +32 -0
- opik/rest_api/types/trace_experiment_item_bulk_write_view.py +41 -0
- 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_public.py +23 -0
- opik/rest_api/types/trace_filter_public_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_page_public.py +8 -10
- opik/rest_api/types/trace_public.py +27 -13
- opik/rest_api/types/trace_public_visibility_mode.py +5 -0
- opik/rest_api/types/trace_thread.py +18 -9
- opik/rest_api/types/trace_thread_filter.py +23 -0
- opik/rest_api/types/trace_thread_filter_operator.py +21 -0
- opik/rest_api/types/trace_thread_filter_public.py +23 -0
- opik/rest_api/types/trace_thread_filter_public_operator.py +21 -0
- 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 +22 -0
- opik/rest_api/types/trace_thread_llm_as_judge_code.py +26 -0
- opik/rest_api/types/trace_thread_llm_as_judge_code_public.py +26 -0
- opik/rest_api/types/trace_thread_llm_as_judge_code_write.py +26 -0
- opik/rest_api/types/trace_thread_page.py +9 -6
- opik/rest_api/types/trace_thread_status.py +5 -0
- opik/rest_api/types/trace_thread_update.py +19 -0
- opik/rest_api/types/trace_thread_user_defined_metric_python_code.py +19 -0
- opik/rest_api/types/trace_thread_user_defined_metric_python_code_public.py +19 -0
- opik/rest_api/types/trace_thread_user_defined_metric_python_code_write.py +19 -0
- opik/rest_api/types/trace_update.py +39 -0
- opik/rest_api/types/trace_visibility_mode.py +5 -0
- opik/rest_api/types/trace_write.py +10 -11
- opik/rest_api/types/usage.py +6 -6
- opik/rest_api/types/user_defined_metric_python_code.py +3 -5
- opik/rest_api/types/user_defined_metric_python_code_public.py +3 -5
- opik/rest_api/types/user_defined_metric_python_code_write.py +3 -5
- opik/rest_api/types/value_entry.py +27 -0
- opik/rest_api/types/value_entry_compare.py +27 -0
- opik/rest_api/types/value_entry_compare_source.py +5 -0
- opik/rest_api/types/value_entry_experiment_item_bulk_write_view.py +27 -0
- opik/rest_api/types/value_entry_experiment_item_bulk_write_view_source.py +5 -0
- opik/rest_api/types/value_entry_public.py +27 -0
- opik/rest_api/types/value_entry_public_source.py +5 -0
- opik/rest_api/types/value_entry_source.py +5 -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 +27 -0
- opik/rest_api/types/workspace_metric_request.py +24 -0
- opik/rest_api/types/workspace_metric_response.py +20 -0
- opik/rest_api/types/workspace_metrics_summary_request.py +23 -0
- opik/rest_api/types/workspace_metrics_summary_response.py +20 -0
- opik/rest_api/types/workspace_name_holder.py +19 -0
- opik/rest_api/types/workspace_spans_count.py +20 -0
- opik/rest_api/types/workspace_trace_count.py +3 -5
- 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/__init__.py +2 -0
- opik/rest_api/workspaces/client.py +550 -77
- opik/rest_api/workspaces/raw_client.py +923 -0
- opik/rest_client_configurator/api.py +1 -0
- opik/rest_client_configurator/retry_decorator.py +1 -0
- opik/s3_httpx_client.py +67 -0
- opik/simulation/__init__.py +6 -0
- opik/simulation/simulated_user.py +99 -0
- opik/simulation/simulator.py +108 -0
- opik/synchronization.py +11 -24
- opik/tracing_runtime_config.py +48 -0
- opik/types.py +48 -2
- opik/url_helpers.py +13 -3
- opik/validation/chat_prompt_messages.py +241 -0
- opik/validation/feedback_score.py +4 -5
- opik/validation/parameter.py +122 -0
- opik/validation/parameters_validator.py +175 -0
- opik/validation/validator.py +30 -2
- opik/validation/validator_helpers.py +147 -0
- opik-1.9.71.dist-info/METADATA +370 -0
- opik-1.9.71.dist-info/RECORD +1110 -0
- {opik-1.6.4.dist-info → opik-1.9.71.dist-info}/WHEEL +1 -1
- opik-1.9.71.dist-info/licenses/LICENSE +203 -0
- opik/api_objects/prompt/prompt.py +0 -107
- opik/api_objects/prompt/prompt_template.py +0 -35
- opik/cli.py +0 -193
- opik/evaluation/metrics/models.py +0 -8
- opik/hooks.py +0 -13
- opik/integrations/bedrock/chunks_aggregator.py +0 -55
- opik/integrations/bedrock/helpers.py +0 -8
- opik/integrations/langchain/google_run_helpers.py +0 -75
- opik/integrations/langchain/openai_run_helpers.py +0 -122
- opik/message_processing/message_processors.py +0 -203
- opik/rest_api/types/delta_role.py +0 -7
- opik/rest_api/types/json_object_schema.py +0 -34
- opik-1.6.4.dist-info/METADATA +0 -270
- opik-1.6.4.dist-info/RECORD +0 -507
- /opik/integrations/bedrock/{stream_wrappers.py → converse/stream_wrappers.py} +0 -0
- {opik-1.6.4.dist-info → opik-1.9.71.dist-info}/entry_points.txt +0 -0
- {opik-1.6.4.dist-info → opik-1.9.71.dist-info}/top_level.txt +0 -0
opik/api_objects/opik_client.py
CHANGED
|
@@ -2,10 +2,32 @@ import atexit
|
|
|
2
2
|
import datetime
|
|
3
3
|
import functools
|
|
4
4
|
import logging
|
|
5
|
-
from typing import Any, Dict, List, Optional, Union
|
|
5
|
+
from typing import Any, Dict, List, Optional, TypeVar, Union, Literal, cast
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
8
|
|
|
9
|
+
from . import (
|
|
10
|
+
constants,
|
|
11
|
+
dataset,
|
|
12
|
+
experiment,
|
|
13
|
+
optimization,
|
|
14
|
+
helpers,
|
|
15
|
+
opik_query_language,
|
|
16
|
+
search_helpers,
|
|
17
|
+
span,
|
|
18
|
+
trace,
|
|
19
|
+
)
|
|
20
|
+
from .attachment import Attachment
|
|
21
|
+
from .attachment import client as attachment_client
|
|
22
|
+
from .attachment import converters as attachment_converters
|
|
23
|
+
from .dataset import rest_operations as dataset_rest_operations
|
|
24
|
+
from .experiment import experiments_client
|
|
25
|
+
from .experiment import helpers as experiment_helpers
|
|
26
|
+
from .experiment import rest_operations as experiment_rest_operations
|
|
27
|
+
from . import prompt as prompt_module
|
|
28
|
+
from .prompt import client as prompt_client
|
|
29
|
+
from .threads import threads_client
|
|
30
|
+
from .trace import migration as trace_migration, trace_client
|
|
9
31
|
from .. import (
|
|
10
32
|
config,
|
|
11
33
|
datetime_helpers,
|
|
@@ -16,31 +38,35 @@ from .. import (
|
|
|
16
38
|
rest_client_configurator,
|
|
17
39
|
url_helpers,
|
|
18
40
|
)
|
|
19
|
-
from ..message_processing import
|
|
41
|
+
from ..message_processing import (
|
|
42
|
+
messages,
|
|
43
|
+
streamer_constructors,
|
|
44
|
+
message_queue,
|
|
45
|
+
)
|
|
20
46
|
from ..message_processing.batching import sequence_splitter
|
|
47
|
+
from ..message_processing.processors import message_processors_chain
|
|
21
48
|
from ..rest_api import client as rest_api_client
|
|
22
49
|
from ..rest_api.core.api_error import ApiError
|
|
23
|
-
from ..rest_api.types import
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
50
|
+
from ..rest_api.types import (
|
|
51
|
+
dataset_public,
|
|
52
|
+
project_public,
|
|
53
|
+
span_public,
|
|
54
|
+
trace_public,
|
|
55
|
+
span_filter_public,
|
|
56
|
+
trace_filter_public,
|
|
57
|
+
)
|
|
58
|
+
from ..types import (
|
|
59
|
+
BatchFeedbackScoreDict,
|
|
60
|
+
ErrorInfoDict,
|
|
61
|
+
FeedbackScoreDict,
|
|
62
|
+
LLMProvider,
|
|
63
|
+
SpanType,
|
|
34
64
|
)
|
|
35
|
-
from .dataset import rest_operations as dataset_rest_operations
|
|
36
|
-
from .experiment import helpers as experiment_helpers
|
|
37
|
-
from .experiment import rest_operations as experiment_rest_operations
|
|
38
|
-
from .prompt import Prompt
|
|
39
|
-
from .prompt.client import PromptClient
|
|
40
|
-
from .trace import migration as trace_migration
|
|
41
65
|
|
|
42
66
|
LOGGER = logging.getLogger(__name__)
|
|
43
67
|
|
|
68
|
+
T = TypeVar("T")
|
|
69
|
+
|
|
44
70
|
|
|
45
71
|
class Opik:
|
|
46
72
|
def __init__(
|
|
@@ -87,10 +113,6 @@ class Opik:
|
|
|
87
113
|
self._use_batching = _use_batching
|
|
88
114
|
|
|
89
115
|
self._initialize_streamer(
|
|
90
|
-
base_url=config_.url_override,
|
|
91
|
-
workers=config_.background_workers,
|
|
92
|
-
api_key=config_.api_key,
|
|
93
|
-
check_tls_certificate=config_.check_tls_certificate,
|
|
94
116
|
use_batching=_use_batching,
|
|
95
117
|
)
|
|
96
118
|
atexit.register(self.end, timeout=self._flush_timeout)
|
|
@@ -103,31 +125,71 @@ class Opik:
|
|
|
103
125
|
"""
|
|
104
126
|
return self._config.model_copy()
|
|
105
127
|
|
|
128
|
+
@property
|
|
129
|
+
def rest_client(self) -> rest_api_client.OpikApi:
|
|
130
|
+
"""
|
|
131
|
+
Provides direct access to the underlying REST API client.
|
|
132
|
+
|
|
133
|
+
WARNING: This client is not guaranteed to be backward compatible with future SDK versions.
|
|
134
|
+
While it provides a convenient way to use the current REST API of Opik.
|
|
135
|
+
However, it's not considered safe to heavily rely on its API as Opik's REST API contracts may change.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
OpikApi: The REST client used by the Opik client.
|
|
139
|
+
"""
|
|
140
|
+
return self._rest_client
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def project_name(self) -> str:
|
|
144
|
+
"""
|
|
145
|
+
This property retrieves the name of the project associated with the instance.
|
|
146
|
+
It is a read-only property.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
str: The name of the project.
|
|
150
|
+
"""
|
|
151
|
+
return self._project_name
|
|
152
|
+
|
|
106
153
|
def _initialize_streamer(
|
|
107
154
|
self,
|
|
108
|
-
base_url: str,
|
|
109
|
-
workers: int,
|
|
110
|
-
api_key: Optional[str],
|
|
111
|
-
check_tls_certificate: bool,
|
|
112
155
|
use_batching: bool,
|
|
113
156
|
) -> None:
|
|
114
|
-
|
|
157
|
+
self._httpx_client = httpx_client.get(
|
|
115
158
|
workspace=self._workspace,
|
|
116
|
-
api_key=api_key,
|
|
117
|
-
check_tls_certificate=check_tls_certificate,
|
|
159
|
+
api_key=self._config.api_key,
|
|
160
|
+
check_tls_certificate=self._config.check_tls_certificate,
|
|
161
|
+
compress_json_requests=self._config.enable_json_request_compression,
|
|
118
162
|
)
|
|
119
163
|
self._rest_client = rest_api_client.OpikApi(
|
|
120
|
-
base_url=
|
|
121
|
-
httpx_client=
|
|
164
|
+
base_url=self._config.url_override,
|
|
165
|
+
httpx_client=self._httpx_client,
|
|
122
166
|
)
|
|
123
167
|
self._rest_client._client_wrapper._timeout = (
|
|
124
168
|
httpx.USE_CLIENT_DEFAULT
|
|
125
169
|
) # See https://github.com/fern-api/fern/issues/5321
|
|
126
170
|
rest_client_configurator.configure(self._rest_client)
|
|
171
|
+
|
|
172
|
+
max_queue_size = message_queue.calculate_max_queue_size(
|
|
173
|
+
maximal_queue_size=self._config.maximal_queue_size,
|
|
174
|
+
batch_factor=self._config.maximal_queue_size_batch_factor,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
self.__internal_api__message_processor__ = (
|
|
178
|
+
message_processors_chain.create_message_processors_chain(
|
|
179
|
+
rest_client=self._rest_client
|
|
180
|
+
)
|
|
181
|
+
)
|
|
127
182
|
self._streamer = streamer_constructors.construct_online_streamer(
|
|
128
|
-
n_consumers=
|
|
183
|
+
n_consumers=self._config.background_workers,
|
|
129
184
|
rest_client=self._rest_client,
|
|
185
|
+
httpx_client=self._httpx_client,
|
|
130
186
|
use_batching=use_batching,
|
|
187
|
+
use_attachment_extraction=self._config.is_attachment_extraction_active,
|
|
188
|
+
min_base64_embedded_attachment_size=self._config.min_base64_embedded_attachment_size,
|
|
189
|
+
file_upload_worker_count=self._config.file_upload_background_workers,
|
|
190
|
+
max_queue_size=max_queue_size,
|
|
191
|
+
message_processor=self.__internal_api__message_processor__,
|
|
192
|
+
url_override=self._config.url_override,
|
|
131
193
|
)
|
|
132
194
|
|
|
133
195
|
def _display_trace_url(self, trace_id: str, project_name: str) -> None:
|
|
@@ -173,13 +235,14 @@ class Opik:
|
|
|
173
235
|
project_name: Optional[str] = None,
|
|
174
236
|
error_info: Optional[ErrorInfoDict] = None,
|
|
175
237
|
thread_id: Optional[str] = None,
|
|
238
|
+
attachments: Optional[List[Attachment]] = None,
|
|
176
239
|
**ignored_kwargs: Any,
|
|
177
240
|
) -> trace.Trace:
|
|
178
241
|
"""
|
|
179
242
|
Create and log a new trace.
|
|
180
243
|
|
|
181
244
|
Args:
|
|
182
|
-
id: The unique identifier for the trace, if not provided a new ID will be generated. Must be a valid [UUIDv7](https://uuid7.com/) ID.
|
|
245
|
+
id: The unique identifier for the trace, if not provided, a new ID will be generated. Must be a valid [UUIDv7](https://uuid7.com/) ID.
|
|
183
246
|
name: The name of the trace.
|
|
184
247
|
start_time: The start time of the trace. If not provided, the current local time will be used.
|
|
185
248
|
end_time: The end time of the trace.
|
|
@@ -193,6 +256,7 @@ class Opik:
|
|
|
193
256
|
error_info: The dictionary with error information (typically used when the trace function has failed).
|
|
194
257
|
thread_id: Used to group multiple traces into a thread.
|
|
195
258
|
The identifier is user-defined and has to be unique per project.
|
|
259
|
+
attachments: The list of attachments to be uploaded to the trace.
|
|
196
260
|
|
|
197
261
|
Returns:
|
|
198
262
|
trace.Trace: The created trace object.
|
|
@@ -201,6 +265,7 @@ class Opik:
|
|
|
201
265
|
start_time = (
|
|
202
266
|
start_time if start_time is not None else datetime_helpers.local_timestamp()
|
|
203
267
|
)
|
|
268
|
+
last_updated_at = datetime_helpers.local_timestamp()
|
|
204
269
|
|
|
205
270
|
if project_name is None:
|
|
206
271
|
project_name = self._project_name
|
|
@@ -217,6 +282,7 @@ class Opik:
|
|
|
217
282
|
tags=tags,
|
|
218
283
|
error_info=error_info,
|
|
219
284
|
thread_id=thread_id,
|
|
285
|
+
last_updated_at=last_updated_at,
|
|
220
286
|
)
|
|
221
287
|
self._streamer.put(create_trace_message)
|
|
222
288
|
self._display_trace_url(trace_id=id, project_name=project_name)
|
|
@@ -225,12 +291,27 @@ class Opik:
|
|
|
225
291
|
for feedback_score in feedback_scores:
|
|
226
292
|
feedback_score["id"] = id
|
|
227
293
|
|
|
228
|
-
self.log_traces_feedback_scores(
|
|
294
|
+
self.log_traces_feedback_scores(
|
|
295
|
+
cast(List[BatchFeedbackScoreDict], feedback_scores), project_name
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
if attachments is not None:
|
|
299
|
+
for attachment_data in attachments:
|
|
300
|
+
self._streamer.put(
|
|
301
|
+
attachment_converters.attachment_to_message(
|
|
302
|
+
attachment_data=attachment_data,
|
|
303
|
+
entity_type="trace",
|
|
304
|
+
entity_id=id,
|
|
305
|
+
project_name=project_name,
|
|
306
|
+
url_override=self._config.url_override,
|
|
307
|
+
)
|
|
308
|
+
)
|
|
229
309
|
|
|
230
310
|
return trace.Trace(
|
|
231
311
|
id=id,
|
|
232
312
|
message_streamer=self._streamer,
|
|
233
313
|
project_name=project_name,
|
|
314
|
+
url_override=self._config.url_override,
|
|
234
315
|
)
|
|
235
316
|
|
|
236
317
|
def copy_traces(
|
|
@@ -248,7 +329,7 @@ class Opik:
|
|
|
248
329
|
|
|
249
330
|
Note: This method is not optimized for large projects, if you run into any issues please raise
|
|
250
331
|
an issue on GitHub. In addition, be aware that deleting traces that are linked to experiments
|
|
251
|
-
will lead to
|
|
332
|
+
will lead to inconsistencies in the UI.
|
|
252
333
|
|
|
253
334
|
Args:
|
|
254
335
|
project_name: The name of the project to copy traces from.
|
|
@@ -287,10 +368,10 @@ class Opik:
|
|
|
287
368
|
)
|
|
288
369
|
|
|
289
370
|
for trace_data_ in new_trace_data:
|
|
290
|
-
self.trace(**trace_data_.
|
|
371
|
+
self.trace(**trace_data_.as_parameters)
|
|
291
372
|
|
|
292
373
|
for span_data_ in new_span_data:
|
|
293
|
-
self.span(**span_data_.
|
|
374
|
+
self.span(**span_data_.as_parameters)
|
|
294
375
|
|
|
295
376
|
if delete_original_project:
|
|
296
377
|
trace_ids = [trace_.id for trace_ in trace_data]
|
|
@@ -320,6 +401,7 @@ class Opik:
|
|
|
320
401
|
provider: Optional[Union[str, LLMProvider]] = None,
|
|
321
402
|
error_info: Optional[ErrorInfoDict] = None,
|
|
322
403
|
total_cost: Optional[float] = None,
|
|
404
|
+
attachments: Optional[List[Attachment]] = None,
|
|
323
405
|
) -> span.Span:
|
|
324
406
|
"""
|
|
325
407
|
Create and log a new span.
|
|
@@ -336,19 +418,20 @@ class Opik:
|
|
|
336
418
|
input: The input data for the span. This can be any valid JSON serializable object.
|
|
337
419
|
output: The output data for the span. This can be any valid JSON serializable object.
|
|
338
420
|
tags: Tags associated with the span.
|
|
339
|
-
feedback_scores: The list of feedback score dicts associated with the span. Dicts don't require
|
|
340
|
-
project_name: The name of the project. If not set, the project name which was configured when Opik instance
|
|
421
|
+
feedback_scores: The list of feedback score dicts associated with the span. Dicts don't require having an `id` value.
|
|
422
|
+
project_name: The name of the project. If not set, the project name which was configured when the Opik instance
|
|
341
423
|
was created will be used.
|
|
342
|
-
usage: Usage data for the span. In order for input, output and total tokens to be visible in the UI,
|
|
343
|
-
the usage must contain OpenAI-formatted keys (they can be passed
|
|
424
|
+
usage: Usage data for the span. In order for input, output, and total tokens to be visible in the UI,
|
|
425
|
+
the usage must contain OpenAI-formatted keys (they can be passed additionally to the original usage on the top level of the dict): prompt_tokens, completion_tokens, and total_tokens.
|
|
344
426
|
If OpenAI-formatted keys were not found, Opik will try to calculate them automatically if the usage
|
|
345
427
|
format is recognized (you can see which provider's formats are recognized in opik.LLMProvider enum), but it is not guaranteed.
|
|
346
428
|
model: The name of LLM (in this case `type` parameter should be == `llm`)
|
|
347
429
|
provider: The provider of LLM. You can find providers officially supported by Opik for cost tracking
|
|
348
|
-
in `opik.LLMProvider` enum. If your provider is not here, please open an issue in our
|
|
349
|
-
If your provider not in the list, you can still specify it but the cost tracking will not be available
|
|
430
|
+
in `opik.LLMProvider` enum. If your provider is not here, please open an issue in our GitHub - https://github.com/comet-ml/opik.
|
|
431
|
+
If your provider is not in the list, you can still specify it, but the cost tracking will not be available
|
|
350
432
|
error_info: The dictionary with error information (typically used when the span function has failed).
|
|
351
433
|
total_cost: The cost of the span in USD. This value takes priority over the cost calculated by Opik from the usage.
|
|
434
|
+
attachments: The list of attachments to be uploaded to the span.
|
|
352
435
|
|
|
353
436
|
Returns:
|
|
354
437
|
span.Span: The created span object.
|
|
@@ -358,15 +441,6 @@ class Opik:
|
|
|
358
441
|
start_time if start_time is not None else datetime_helpers.local_timestamp()
|
|
359
442
|
)
|
|
360
443
|
|
|
361
|
-
backend_compatible_usage = validation_helpers.validate_and_parse_usage(
|
|
362
|
-
usage=usage,
|
|
363
|
-
logger=LOGGER,
|
|
364
|
-
provider=provider,
|
|
365
|
-
)
|
|
366
|
-
|
|
367
|
-
if backend_compatible_usage is not None:
|
|
368
|
-
metadata = helpers.add_usage_to_metadata(usage=usage, metadata=metadata)
|
|
369
|
-
|
|
370
444
|
if project_name is None:
|
|
371
445
|
project_name = self._project_name
|
|
372
446
|
|
|
@@ -386,13 +460,24 @@ class Opik:
|
|
|
386
460
|
tags=tags,
|
|
387
461
|
error_info=error_info,
|
|
388
462
|
thread_id=None,
|
|
463
|
+
last_updated_at=datetime_helpers.local_timestamp(),
|
|
389
464
|
)
|
|
390
465
|
self._streamer.put(create_trace_message)
|
|
391
466
|
|
|
392
|
-
|
|
393
|
-
|
|
467
|
+
if feedback_scores is not None:
|
|
468
|
+
for feedback_score in feedback_scores:
|
|
469
|
+
feedback_score["id"] = id
|
|
470
|
+
|
|
471
|
+
self.log_spans_feedback_scores(
|
|
472
|
+
cast(List[BatchFeedbackScoreDict], feedback_scores), project_name
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
return span.span_client.create_span(
|
|
394
476
|
trace_id=trace_id,
|
|
395
477
|
project_name=project_name,
|
|
478
|
+
url_override=self._config.url_override,
|
|
479
|
+
message_streamer=self._streamer,
|
|
480
|
+
span_id=id,
|
|
396
481
|
parent_span_id=parent_span_id,
|
|
397
482
|
name=name,
|
|
398
483
|
type=type,
|
|
@@ -402,60 +487,194 @@ class Opik:
|
|
|
402
487
|
output=output,
|
|
403
488
|
metadata=metadata,
|
|
404
489
|
tags=tags,
|
|
405
|
-
usage=
|
|
490
|
+
usage=usage,
|
|
406
491
|
model=model,
|
|
407
492
|
provider=provider,
|
|
408
493
|
error_info=error_info,
|
|
409
494
|
total_cost=total_cost,
|
|
495
|
+
attachments=attachments,
|
|
410
496
|
)
|
|
411
|
-
self._streamer.put(create_span_message)
|
|
412
497
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
498
|
+
def update_span(
|
|
499
|
+
self,
|
|
500
|
+
id: str,
|
|
501
|
+
trace_id: str,
|
|
502
|
+
parent_span_id: Optional[str],
|
|
503
|
+
project_name: str,
|
|
504
|
+
end_time: Optional[datetime.datetime] = None,
|
|
505
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
506
|
+
input: Optional[Dict[str, Any]] = None,
|
|
507
|
+
output: Optional[Dict[str, Any]] = None,
|
|
508
|
+
tags: Optional[List[str]] = None,
|
|
509
|
+
usage: Optional[Union[Dict[str, Any], llm_usage.OpikUsage]] = None,
|
|
510
|
+
model: Optional[str] = None,
|
|
511
|
+
provider: Optional[Union[LLMProvider, str]] = None,
|
|
512
|
+
error_info: Optional[ErrorInfoDict] = None,
|
|
513
|
+
total_cost: Optional[float] = None,
|
|
514
|
+
attachments: Optional[List[Attachment]] = None,
|
|
515
|
+
) -> None:
|
|
516
|
+
"""
|
|
517
|
+
Update the attributes of an existing span.
|
|
416
518
|
|
|
417
|
-
|
|
519
|
+
This method should only be used after the span has been fully created and stored.
|
|
520
|
+
If called before or immediately after span creation, the update may silently fail or result in incorrect data.
|
|
418
521
|
|
|
419
|
-
|
|
522
|
+
This method uses four parameters to identify the span:
|
|
523
|
+
- `id`
|
|
524
|
+
- `trace_id`
|
|
525
|
+
- `parent_span_id`
|
|
526
|
+
- `project_name`
|
|
527
|
+
|
|
528
|
+
These parameters **must match exactly** the values used when the span was created.
|
|
529
|
+
If any of them are incorrect, the update may not apply and no error will be raised.
|
|
530
|
+
|
|
531
|
+
All other parameters are optional and will update the corresponding fields in the span.
|
|
532
|
+
If a parameter is not provided, the existing value will remain unchanged.
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
id: The unique identifier for the span to update.
|
|
536
|
+
trace_id: The unique identifier for the trace to which the span belongs.
|
|
537
|
+
parent_span_id: The unique identifier for the parent span.
|
|
538
|
+
project_name: The project name to which the span belongs.
|
|
539
|
+
end_time: The new end time of the span.
|
|
540
|
+
metadata: The new metadata to be associated with the span.
|
|
541
|
+
input: The new input data for the span.
|
|
542
|
+
output: The new output data for the span.
|
|
543
|
+
tags: A new list of tags to be associated with the span.
|
|
544
|
+
usage: The new usage data for the span. In order for input, output and total tokens to be visible in the UI,
|
|
545
|
+
the usage must contain OpenAI-formatted keys (they can be passed additionaly to original usage on the top level of the dict): prompt_tokens, completion_tokens and total_tokens.
|
|
546
|
+
If OpenAI-formatted keys were not found, Opik will try to calculate them automatically if the usage
|
|
547
|
+
format is recognized (you can see which provider's formats are recognized in opik.LLMProvider enum), but it is not guaranteed.
|
|
548
|
+
model: The new name of LLM.
|
|
549
|
+
provider: The new provider of LLM. You can find providers officially supported by Opik for cost tracking
|
|
550
|
+
in `opik.LLMProvider` enum. If your provider is not here, please open an issue in our github - https://github.com/comet-ml/opik.
|
|
551
|
+
If your provider not in the list, you can still specify it but the cost tracking will not be available
|
|
552
|
+
error_info: The new dictionary with error information (typically used when the span function has failed).
|
|
553
|
+
total_cost: The new cost of the span in USD. This value takes priority over the cost calculated by Opik from the usage.
|
|
554
|
+
attachments: The new list of attachments to be uploaded to the span.
|
|
555
|
+
|
|
556
|
+
Returns:
|
|
557
|
+
None
|
|
558
|
+
"""
|
|
559
|
+
span.span_client.update_span(
|
|
420
560
|
id=id,
|
|
561
|
+
trace_id=trace_id,
|
|
421
562
|
parent_span_id=parent_span_id,
|
|
563
|
+
url_override=self._config.url_override,
|
|
564
|
+
message_streamer=self._streamer,
|
|
565
|
+
project_name=project_name,
|
|
566
|
+
end_time=end_time,
|
|
567
|
+
metadata=metadata,
|
|
568
|
+
input=input,
|
|
569
|
+
output=output,
|
|
570
|
+
tags=tags,
|
|
571
|
+
usage=usage,
|
|
572
|
+
model=model,
|
|
573
|
+
provider=provider,
|
|
574
|
+
error_info=error_info,
|
|
575
|
+
total_cost=total_cost,
|
|
576
|
+
attachments=attachments,
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
def update_trace(
|
|
580
|
+
self,
|
|
581
|
+
trace_id: str,
|
|
582
|
+
project_name: str,
|
|
583
|
+
end_time: Optional[datetime.datetime] = None,
|
|
584
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
585
|
+
input: Optional[Dict[str, Any]] = None,
|
|
586
|
+
output: Optional[Dict[str, Any]] = None,
|
|
587
|
+
tags: Optional[List[Any]] = None,
|
|
588
|
+
error_info: Optional[ErrorInfoDict] = None,
|
|
589
|
+
thread_id: Optional[str] = None,
|
|
590
|
+
) -> None:
|
|
591
|
+
"""
|
|
592
|
+
Update the trace attributes.
|
|
593
|
+
|
|
594
|
+
This method should only be used after the trace has been fully created and stored.
|
|
595
|
+
If called before or immediately after trace creation, the update may silently fail or result in incorrect data.
|
|
596
|
+
|
|
597
|
+
This method uses two parameters to identify the trace:
|
|
598
|
+
- `trace_id`
|
|
599
|
+
- `project_name`
|
|
600
|
+
|
|
601
|
+
These parameters **must match exactly** the values used when the trace was created.
|
|
602
|
+
If any of them are incorrect, the update may not apply and no error will be raised.
|
|
603
|
+
|
|
604
|
+
All other parameters are optional and will update the corresponding fields in the trace.
|
|
605
|
+
If a parameter is not provided, the existing value will remain unchanged.
|
|
606
|
+
|
|
607
|
+
Args:
|
|
608
|
+
trace_id: The unique identifier for the trace.
|
|
609
|
+
project_name: The project name to which the trace belongs.
|
|
610
|
+
end_time: The end time of the trace.
|
|
611
|
+
metadata: Additional metadata to be associated with the trace.
|
|
612
|
+
input: The input data for the trace.
|
|
613
|
+
output: The output data for the trace.
|
|
614
|
+
tags: A list of tags to be associated with the trace.
|
|
615
|
+
error_info: The dictionary with error information (typically used when the trace function has failed).
|
|
616
|
+
thread_id: Used to group multiple traces into a thread.
|
|
617
|
+
The identifier is user-defined and has to be unique per project.
|
|
618
|
+
|
|
619
|
+
Returns:
|
|
620
|
+
None
|
|
621
|
+
"""
|
|
622
|
+
if not trace_id or not project_name:
|
|
623
|
+
raise ValueError(
|
|
624
|
+
"trace_id and project_name must be provided and can not be None or empty, "
|
|
625
|
+
f"trace_id: {trace_id}, project_name: {project_name}"
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
trace_client.update_trace(
|
|
422
629
|
trace_id=trace_id,
|
|
423
630
|
project_name=project_name,
|
|
424
631
|
message_streamer=self._streamer,
|
|
632
|
+
end_time=end_time,
|
|
633
|
+
metadata=metadata,
|
|
634
|
+
input=input,
|
|
635
|
+
output=output,
|
|
636
|
+
tags=tags,
|
|
637
|
+
error_info=error_info,
|
|
638
|
+
thread_id=thread_id,
|
|
425
639
|
)
|
|
426
640
|
|
|
427
641
|
def log_spans_feedback_scores(
|
|
428
|
-
self, scores: List[
|
|
642
|
+
self, scores: List[BatchFeedbackScoreDict], project_name: Optional[str] = None
|
|
429
643
|
) -> None:
|
|
430
644
|
"""
|
|
431
645
|
Log feedback scores for spans.
|
|
432
646
|
|
|
433
647
|
Args:
|
|
434
|
-
scores (List[
|
|
648
|
+
scores (List[BatchFeedbackScoreDict]): A list of feedback score dictionaries.
|
|
435
649
|
Specifying a span id via `id` key for each score is mandatory.
|
|
436
650
|
project_name: The name of the project in which the spans are logged. If not set, the project name
|
|
437
|
-
which was configured when Opik instance was created will be used.
|
|
651
|
+
which was configured when the Opik instance was created will be used.
|
|
652
|
+
Deprecated: use `project_name` in the feedback score dictionary that's listed in the `scores` parameter.
|
|
438
653
|
|
|
439
654
|
Returns:
|
|
440
655
|
None
|
|
441
|
-
"""
|
|
442
|
-
valid_scores = [
|
|
443
|
-
score
|
|
444
|
-
for score in scores
|
|
445
|
-
if validation_helpers.validate_feedback_score(score, LOGGER) is not None
|
|
446
|
-
]
|
|
447
656
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
657
|
+
Example:
|
|
658
|
+
>>> from opik import Opik
|
|
659
|
+
>>> client = Opik()
|
|
660
|
+
>>> # Batch logging across multiple projects
|
|
661
|
+
>>> scores = [
|
|
662
|
+
>>> {"id": span1_id, "name": "accuracy", "value": 0.95, "project_name": "project-A"},
|
|
663
|
+
>>> {"id": span2_id, "name": "accuracy", "value": 0.88, "project_name": "project-B"},
|
|
664
|
+
>>> ]
|
|
665
|
+
>>> client.log_spans_feedback_scores(scores=scores)
|
|
666
|
+
"""
|
|
667
|
+
score_messages = helpers.parse_feedback_score_messages(
|
|
668
|
+
scores=scores,
|
|
669
|
+
project_name=project_name or self.project_name,
|
|
670
|
+
parsed_item_class=messages.FeedbackScoreMessage,
|
|
671
|
+
logger=LOGGER,
|
|
672
|
+
)
|
|
673
|
+
if score_messages is None:
|
|
674
|
+
LOGGER.error(
|
|
675
|
+
f"No valid spans feedback scores to log from provided ones: {scores}"
|
|
456
676
|
)
|
|
457
|
-
|
|
458
|
-
]
|
|
677
|
+
return
|
|
459
678
|
|
|
460
679
|
for batch in sequence_splitter.split_into_batches(
|
|
461
680
|
score_messages,
|
|
@@ -469,47 +688,84 @@ class Opik:
|
|
|
469
688
|
self._streamer.put(add_span_feedback_scores_batch_message)
|
|
470
689
|
|
|
471
690
|
def log_traces_feedback_scores(
|
|
472
|
-
self, scores: List[
|
|
691
|
+
self, scores: List[BatchFeedbackScoreDict], project_name: Optional[str] = None
|
|
473
692
|
) -> None:
|
|
474
693
|
"""
|
|
475
694
|
Log feedback scores for traces.
|
|
476
695
|
|
|
477
696
|
Args:
|
|
478
|
-
scores (List[
|
|
697
|
+
scores (List[BatchFeedbackScoreDict]): A list of feedback score dictionaries.
|
|
479
698
|
Specifying a trace id via `id` key for each score is mandatory.
|
|
480
699
|
project_name: The name of the project in which the traces are logged. If not set, the project name
|
|
481
|
-
which was configured when Opik instance was created will be used.
|
|
700
|
+
which was configured when the Opik instance was created will be used.
|
|
701
|
+
Deprecated: use `project_name` in the feedback score dictionary that's listed in the `scores` parameter.
|
|
482
702
|
|
|
483
703
|
Returns:
|
|
484
704
|
None
|
|
485
|
-
"""
|
|
486
|
-
valid_scores = [
|
|
487
|
-
score
|
|
488
|
-
for score in scores
|
|
489
|
-
if validation_helpers.validate_feedback_score(score, LOGGER) is not None
|
|
490
|
-
]
|
|
491
705
|
|
|
492
|
-
|
|
493
|
-
|
|
706
|
+
Example:
|
|
707
|
+
>>> from opik import Opik
|
|
708
|
+
>>> client = Opik()
|
|
709
|
+
>>> # Batch logging across multiple projects
|
|
710
|
+
>>> scores = [
|
|
711
|
+
>>> {"id": trace1_id, "name": "accuracy", "value": 0.95, "project_name": "project-A"},
|
|
712
|
+
>>> {"id": trace2_id, "name": "accuracy", "value": 0.88, "project_name": "project-B"},
|
|
713
|
+
>>> ]
|
|
714
|
+
>>> client.log_traces_feedback_scores(scores=scores)
|
|
715
|
+
"""
|
|
716
|
+
score_messages = helpers.parse_feedback_score_messages(
|
|
717
|
+
scores=scores,
|
|
718
|
+
project_name=project_name or self.project_name,
|
|
719
|
+
parsed_item_class=messages.FeedbackScoreMessage,
|
|
720
|
+
logger=LOGGER,
|
|
721
|
+
)
|
|
494
722
|
|
|
495
|
-
score_messages
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
project_name=project_name or self._project_name,
|
|
499
|
-
**score_dict,
|
|
723
|
+
if score_messages is None:
|
|
724
|
+
LOGGER.error(
|
|
725
|
+
f"No valid traces feedback scores to log from provided ones: {scores}"
|
|
500
726
|
)
|
|
501
|
-
|
|
502
|
-
|
|
727
|
+
return
|
|
728
|
+
|
|
503
729
|
for batch in sequence_splitter.split_into_batches(
|
|
504
730
|
score_messages,
|
|
505
731
|
max_payload_size_MB=config.MAX_BATCH_SIZE_MB,
|
|
506
732
|
max_length=constants.FEEDBACK_SCORES_MAX_BATCH_SIZE,
|
|
507
733
|
):
|
|
508
|
-
|
|
734
|
+
add_trace_feedback_scores_batch_message = (
|
|
509
735
|
messages.AddTraceFeedbackScoresBatchMessage(batch=batch)
|
|
510
736
|
)
|
|
511
737
|
|
|
512
|
-
self._streamer.put(
|
|
738
|
+
self._streamer.put(add_trace_feedback_scores_batch_message)
|
|
739
|
+
|
|
740
|
+
def log_threads_feedback_scores(
|
|
741
|
+
self, scores: List[BatchFeedbackScoreDict], project_name: Optional[str] = None
|
|
742
|
+
) -> None:
|
|
743
|
+
"""
|
|
744
|
+
Log feedback scores for threads.
|
|
745
|
+
|
|
746
|
+
Args:
|
|
747
|
+
scores (List[BatchFeedbackScoreDict]): A list of feedback score dictionaries.
|
|
748
|
+
Specifying a thread id via `id` key for each score is mandatory.
|
|
749
|
+
project_name: The name of the project in which the threads are logged. If not set, the project name
|
|
750
|
+
which was configured when the Opik instance was created will be used.
|
|
751
|
+
Deprecated: use `project_name` in the feedback score dictionary that's listed in the `scores` parameter.
|
|
752
|
+
|
|
753
|
+
Returns:
|
|
754
|
+
None
|
|
755
|
+
|
|
756
|
+
Example:
|
|
757
|
+
>>> from opik import Opik
|
|
758
|
+
>>> client = Opik()
|
|
759
|
+
>>> # Batch logging across multiple projects
|
|
760
|
+
>>> scores = [
|
|
761
|
+
>>> {"id": "thread_123", "name": "user_satisfaction", "value": 0.85, "project_name": "project-A"},
|
|
762
|
+
>>> {"id": "thread_456", "name": "user_satisfaction", "value": 0.92, "project_name": "project-B"},
|
|
763
|
+
>>> ]
|
|
764
|
+
>>> client.log_threads_feedback_scores(scores=scores)
|
|
765
|
+
"""
|
|
766
|
+
self.get_threads_client().log_threads_feedback_scores(
|
|
767
|
+
scores=scores, project_name=project_name
|
|
768
|
+
)
|
|
513
769
|
|
|
514
770
|
def delete_trace_feedback_score(self, trace_id: str, name: str) -> None:
|
|
515
771
|
"""
|
|
@@ -611,8 +867,13 @@ class Opik:
|
|
|
611
867
|
self._rest_client, dataset_name
|
|
612
868
|
)
|
|
613
869
|
|
|
870
|
+
experiments_client = self.get_experiments_client()
|
|
614
871
|
experiments = dataset_rest_operations.get_dataset_experiments(
|
|
615
|
-
self._rest_client,
|
|
872
|
+
rest_client=self._rest_client,
|
|
873
|
+
dataset_id=dataset_id,
|
|
874
|
+
max_results=max_results,
|
|
875
|
+
streamer=self._streamer,
|
|
876
|
+
experiments_client=experiments_client,
|
|
616
877
|
)
|
|
617
878
|
|
|
618
879
|
return experiments
|
|
@@ -676,8 +937,10 @@ class Opik:
|
|
|
676
937
|
dataset_name: str,
|
|
677
938
|
name: Optional[str] = None,
|
|
678
939
|
experiment_config: Optional[Dict[str, Any]] = None,
|
|
679
|
-
prompt: Optional[
|
|
680
|
-
prompts: Optional[List[
|
|
940
|
+
prompt: Optional[prompt_module.base_prompt.BasePrompt] = None,
|
|
941
|
+
prompts: Optional[List[prompt_module.base_prompt.BasePrompt]] = None,
|
|
942
|
+
type: Literal["regular", "trial", "mini-batch"] = "regular",
|
|
943
|
+
optimization_id: Optional[str] = None,
|
|
681
944
|
) -> experiment.Experiment:
|
|
682
945
|
"""
|
|
683
946
|
Creates a new experiment using the given dataset name and optional parameters.
|
|
@@ -688,6 +951,9 @@ class Opik:
|
|
|
688
951
|
experiment_config: Optional experiment configuration parameters. Must be a dictionary if provided.
|
|
689
952
|
prompt: Prompt object to associate with the experiment. Deprecated, use `prompts` argument instead.
|
|
690
953
|
prompts: List of Prompt objects to associate with the experiment.
|
|
954
|
+
type: The type of the experiment. Can be "regular", "trial", or "mini-batch".
|
|
955
|
+
Defaults to "regular". "trial" and "mini-batch" are only relevant for prompt optimization experiments.
|
|
956
|
+
optimization_id: Optional ID of the optimization associated with the experiment.
|
|
691
957
|
|
|
692
958
|
Returns:
|
|
693
959
|
experiment.Experiment: The newly created experiment object.
|
|
@@ -710,6 +976,8 @@ class Opik:
|
|
|
710
976
|
id=id,
|
|
711
977
|
metadata=metadata,
|
|
712
978
|
prompt_versions=prompt_versions,
|
|
979
|
+
type=type,
|
|
980
|
+
optimization_id=optimization_id,
|
|
713
981
|
)
|
|
714
982
|
|
|
715
983
|
experiment_ = experiment.Experiment(
|
|
@@ -717,11 +985,49 @@ class Opik:
|
|
|
717
985
|
name=name,
|
|
718
986
|
dataset_name=dataset_name,
|
|
719
987
|
rest_client=self._rest_client,
|
|
988
|
+
streamer=self._streamer,
|
|
989
|
+
experiments_client=self.get_experiments_client(),
|
|
720
990
|
prompts=checked_prompts,
|
|
721
991
|
)
|
|
722
992
|
|
|
723
993
|
return experiment_
|
|
724
994
|
|
|
995
|
+
def update_experiment(
|
|
996
|
+
self,
|
|
997
|
+
id: str,
|
|
998
|
+
name: Optional[str] = None,
|
|
999
|
+
experiment_config: Optional[Dict[str, Any]] = None,
|
|
1000
|
+
) -> None:
|
|
1001
|
+
"""
|
|
1002
|
+
Update an experiment's name and/or configuration.
|
|
1003
|
+
|
|
1004
|
+
Args:
|
|
1005
|
+
id: The experiment ID.
|
|
1006
|
+
name: The new name for the experiment. If None, the name will not be updated.
|
|
1007
|
+
experiment_config: The new configuration for the experiment. If None, the configuration will not be updated.
|
|
1008
|
+
|
|
1009
|
+
Raises:
|
|
1010
|
+
ValueError: if id is None or empty, or if both name and experiment_config are None
|
|
1011
|
+
"""
|
|
1012
|
+
if not id:
|
|
1013
|
+
raise ValueError(
|
|
1014
|
+
f"id must be provided and can not be None or empty, id: {id}"
|
|
1015
|
+
)
|
|
1016
|
+
|
|
1017
|
+
if name is None and experiment_config is None:
|
|
1018
|
+
raise ValueError(
|
|
1019
|
+
"At least one of 'name' or 'experiment_config' must be provided"
|
|
1020
|
+
)
|
|
1021
|
+
|
|
1022
|
+
# Only include parameters that are provided to avoid clearing fields
|
|
1023
|
+
request_params: Dict[str, Any] = {}
|
|
1024
|
+
if name is not None:
|
|
1025
|
+
request_params["name"] = name
|
|
1026
|
+
if experiment_config is not None:
|
|
1027
|
+
request_params["metadata"] = experiment_config
|
|
1028
|
+
|
|
1029
|
+
self._rest_client.experiments.update_experiment(id, **request_params)
|
|
1030
|
+
|
|
725
1031
|
def get_experiment_by_name(self, name: str) -> experiment.Experiment:
|
|
726
1032
|
"""
|
|
727
1033
|
Returns an existing experiment by its name.
|
|
@@ -741,18 +1047,20 @@ class Opik:
|
|
|
741
1047
|
|
|
742
1048
|
return experiment.Experiment(
|
|
743
1049
|
id=experiment_public.id,
|
|
744
|
-
name=name,
|
|
1050
|
+
name=experiment_public.name,
|
|
745
1051
|
dataset_name=experiment_public.dataset_name,
|
|
746
1052
|
rest_client=self._rest_client,
|
|
747
|
-
|
|
1053
|
+
streamer=self._streamer,
|
|
1054
|
+
experiments_client=self.get_experiments_client(),
|
|
748
1055
|
)
|
|
749
1056
|
|
|
750
1057
|
def get_experiments_by_name(self, name: str) -> List[experiment.Experiment]:
|
|
751
1058
|
"""
|
|
752
|
-
Returns
|
|
1059
|
+
Returns a list of existing experiments containing the given string in their name.
|
|
1060
|
+
Search is case-insensitive.
|
|
753
1061
|
|
|
754
1062
|
Args:
|
|
755
|
-
name: The
|
|
1063
|
+
name: The string to search for in the experiment names.
|
|
756
1064
|
|
|
757
1065
|
Returns:
|
|
758
1066
|
List[experiment.Experiment]: List of existing experiments.
|
|
@@ -765,9 +1073,11 @@ class Opik:
|
|
|
765
1073
|
for public_experiment in experiments_public:
|
|
766
1074
|
experiment_ = experiment.Experiment(
|
|
767
1075
|
id=public_experiment.id,
|
|
1076
|
+
name=public_experiment.name,
|
|
768
1077
|
dataset_name=public_experiment.dataset_name,
|
|
769
|
-
name=name,
|
|
770
1078
|
rest_client=self._rest_client,
|
|
1079
|
+
streamer=self._streamer,
|
|
1080
|
+
experiments_client=self.get_experiments_client(),
|
|
771
1081
|
)
|
|
772
1082
|
result.append(experiment_)
|
|
773
1083
|
|
|
@@ -799,7 +1109,8 @@ class Opik:
|
|
|
799
1109
|
name=experiment_public.name,
|
|
800
1110
|
dataset_name=experiment_public.dataset_name,
|
|
801
1111
|
rest_client=self._rest_client,
|
|
802
|
-
|
|
1112
|
+
streamer=self._streamer,
|
|
1113
|
+
experiments_client=self.get_experiments_client(),
|
|
803
1114
|
)
|
|
804
1115
|
|
|
805
1116
|
def end(self, timeout: Optional[int] = None) -> None:
|
|
@@ -815,7 +1126,7 @@ class Opik:
|
|
|
815
1126
|
timeout = timeout if timeout is not None else self._flush_timeout
|
|
816
1127
|
self._streamer.close(timeout)
|
|
817
1128
|
|
|
818
|
-
def flush(self, timeout: Optional[int] = None) ->
|
|
1129
|
+
def flush(self, timeout: Optional[int] = None) -> bool:
|
|
819
1130
|
"""
|
|
820
1131
|
Flush the streamer to ensure all messages are sent.
|
|
821
1132
|
|
|
@@ -823,10 +1134,10 @@ class Opik:
|
|
|
823
1134
|
timeout (Optional[int]): The timeout for flushing the streamer. Once the timeout is reached, the flush method will return regardless of whether all messages have been sent.
|
|
824
1135
|
|
|
825
1136
|
Returns:
|
|
826
|
-
|
|
1137
|
+
True if all messages have been sent within specified timeout, False otherwise.
|
|
827
1138
|
"""
|
|
828
1139
|
timeout = timeout if timeout is not None else self._flush_timeout
|
|
829
|
-
self._streamer.flush(timeout)
|
|
1140
|
+
return self._streamer.flush(timeout)
|
|
830
1141
|
|
|
831
1142
|
def search_traces(
|
|
832
1143
|
self,
|
|
@@ -834,39 +1145,90 @@ class Opik:
|
|
|
834
1145
|
filter_string: Optional[str] = None,
|
|
835
1146
|
max_results: int = 1000,
|
|
836
1147
|
truncate: bool = True,
|
|
1148
|
+
wait_for_at_least: Optional[int] = None,
|
|
1149
|
+
wait_for_timeout: int = httpx_client.READ_TIMEOUT_SECONDS,
|
|
837
1150
|
) -> List[trace_public.TracePublic]:
|
|
838
1151
|
"""
|
|
839
|
-
Search for traces in the given project.
|
|
1152
|
+
Search for traces in the given project. Optionally, you can wait for at least a certain number of traces
|
|
1153
|
+
to be found before returning within the specified timeout. If wait_for_at_least number of traces are not found
|
|
1154
|
+
within the specified timeout, an exception will be raised.
|
|
840
1155
|
|
|
841
1156
|
Args:
|
|
842
1157
|
project_name: The name of the project to search traces in. If not provided, will search across the project name configured when the Client was created which defaults to the `Default Project`.
|
|
843
|
-
filter_string: A filter string to narrow down the search
|
|
1158
|
+
filter_string: A filter string to narrow down the search using Opik Query Language (OQL).
|
|
1159
|
+
The format is: "<COLUMN> <OPERATOR> <VALUE> [AND <COLUMN> <OPERATOR> <VALUE>]*"
|
|
1160
|
+
|
|
1161
|
+
Supported columns include:
|
|
1162
|
+
- `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: String fields with full operator support
|
|
1163
|
+
- `status`: String field (=, contains, not_contains only)
|
|
1164
|
+
- `start_time`, `end_time`: DateTime fields (use ISO 8601 format, e.g., "2024-01-01T00:00:00Z")
|
|
1165
|
+
- `input`, `output`: String fields for content (=, contains, not_contains only)
|
|
1166
|
+
- `metadata`: Dictionary field (use dot notation, e.g., "metadata.model")
|
|
1167
|
+
- `feedback_scores`: Numeric field (use dot notation, e.g., "feedback_scores.accuracy")
|
|
1168
|
+
- `tags`: List field (use "contains" operator only)
|
|
1169
|
+
- `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`: Numeric usage fields
|
|
1170
|
+
- `duration`, `number_of_messages`, `total_estimated_cost`: Numeric fields
|
|
1171
|
+
|
|
1172
|
+
Supported operators by column:
|
|
1173
|
+
- `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: =, !=, contains, not_contains, starts_with, ends_with, >, <
|
|
1174
|
+
- `status`: =, contains, not_contains
|
|
1175
|
+
- `start_time`, `end_time`: =, >, <, >=, <=
|
|
1176
|
+
- `input`, `output`: =, contains, not_contains
|
|
1177
|
+
- `metadata`: =, contains, >, <
|
|
1178
|
+
- `feedback_scores`: =, >, <, >=, <=, is_empty, is_not_empty
|
|
1179
|
+
- `tags`: contains (only)
|
|
1180
|
+
- `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`, `duration`, `number_of_messages`, `total_estimated_cost`: =, !=, >, <, >=, <=
|
|
1181
|
+
|
|
1182
|
+
Examples:
|
|
1183
|
+
- `start_time >= "2024-01-01T00:00:00Z"` - Filter by start date
|
|
1184
|
+
- `start_time > "2024-01-01T00:00:00Z" AND start_time < "2024-02-01T00:00:00Z"` - Date range
|
|
1185
|
+
- `input contains "question"` - Filter by input content
|
|
1186
|
+
- `usage.total_tokens > 1000` - Filter by token usage
|
|
1187
|
+
- `feedback_scores.accuracy > 0.8` - Filter by feedback score
|
|
1188
|
+
- `feedback_scores.my_metric is_empty` - Filter traces with empty feedback score
|
|
1189
|
+
- `feedback_scores.my_metric is_not_empty` - Filter traces with non-empty feedback score
|
|
1190
|
+
- `tags contains "production"` - Filter by tag
|
|
1191
|
+
- `metadata.model = "gpt-4"` - Filter by metadata field
|
|
1192
|
+
- `thread_id = "thread_123"` - Filter by thread ID
|
|
1193
|
+
|
|
1194
|
+
If not provided, all traces in the project will be returned up to the limit.
|
|
844
1195
|
max_results: The maximum number of traces to return.
|
|
845
|
-
truncate: Whether to truncate image data stored in input, output or metadata
|
|
1196
|
+
truncate: Whether to truncate image data stored in input, output, or metadata
|
|
1197
|
+
wait_for_at_least: The minimum number of traces to wait for before returning.
|
|
1198
|
+
wait_for_timeout: The timeout for waiting for traces.
|
|
1199
|
+
|
|
1200
|
+
Raises:
|
|
1201
|
+
exceptions.SearchTimeoutError if wait_for_at_least traces are not found within the specified timeout.
|
|
846
1202
|
"""
|
|
1203
|
+
filters_ = helpers.parse_filter_expressions(
|
|
1204
|
+
filter_string, parsed_item_class=trace_filter_public.TraceFilterPublic
|
|
1205
|
+
)
|
|
847
1206
|
|
|
848
|
-
|
|
849
|
-
|
|
1207
|
+
search_functor = functools.partial(
|
|
1208
|
+
search_helpers.search_traces_with_filters,
|
|
1209
|
+
rest_client=self._rest_client,
|
|
1210
|
+
project_name=project_name or self._project_name,
|
|
1211
|
+
filters=filters_,
|
|
1212
|
+
max_results=max_results,
|
|
1213
|
+
truncate=truncate,
|
|
1214
|
+
)
|
|
850
1215
|
|
|
851
|
-
|
|
1216
|
+
if wait_for_at_least is None:
|
|
1217
|
+
return search_functor()
|
|
852
1218
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1219
|
+
# do synchronization with backend if wait_for_at_least is provided until a specific number of traces are found
|
|
1220
|
+
result = search_helpers.search_and_wait_for_done(
|
|
1221
|
+
search_functor=search_functor,
|
|
1222
|
+
wait_for_at_least=wait_for_at_least,
|
|
1223
|
+
wait_for_timeout=wait_for_timeout,
|
|
1224
|
+
sleep_time=5,
|
|
1225
|
+
)
|
|
1226
|
+
if len(result) < wait_for_at_least:
|
|
1227
|
+
raise exceptions.SearchTimeoutError(
|
|
1228
|
+
f"Timeout after {wait_for_timeout} seconds: expected {wait_for_at_least} traces, but only {len(result)} were found."
|
|
861
1229
|
)
|
|
862
1230
|
|
|
863
|
-
|
|
864
|
-
break
|
|
865
|
-
|
|
866
|
-
traces.extend(page_traces.content)
|
|
867
|
-
page += 1
|
|
868
|
-
|
|
869
|
-
return traces[:max_results]
|
|
1231
|
+
return result
|
|
870
1232
|
|
|
871
1233
|
def search_spans(
|
|
872
1234
|
self,
|
|
@@ -875,41 +1237,93 @@ class Opik:
|
|
|
875
1237
|
filter_string: Optional[str] = None,
|
|
876
1238
|
max_results: int = 1000,
|
|
877
1239
|
truncate: bool = True,
|
|
1240
|
+
wait_for_at_least: Optional[int] = None,
|
|
1241
|
+
wait_for_timeout: int = httpx_client.READ_TIMEOUT_SECONDS,
|
|
878
1242
|
) -> List[span_public.SpanPublic]:
|
|
879
1243
|
"""
|
|
880
1244
|
Search for spans in the given trace. This allows you to search spans based on the span input, output,
|
|
881
|
-
metadata, tags, etc or based on the trace ID.
|
|
1245
|
+
metadata, tags, etc. or based on the trace ID. Also, you can wait for at least a certain number of spans
|
|
1246
|
+
to be found before returning within the specified timeout. If wait_for_at_least number of spans are not found
|
|
1247
|
+
within the specified timeout, an exception will be raised.
|
|
882
1248
|
|
|
883
1249
|
Args:
|
|
884
1250
|
project_name: The name of the project to search spans in. If not provided, will search across the project name configured when the Client was created which defaults to the `Default Project`.
|
|
885
1251
|
trace_id: The ID of the trace to search spans in. If provided, the search will be limited to the spans in the given trace.
|
|
886
|
-
filter_string: A filter string to narrow down the search.
|
|
1252
|
+
filter_string: A filter string to narrow down the search using Opik Query Language (OQL).
|
|
1253
|
+
The format is: "<COLUMN> <OPERATOR> <VALUE> [AND <COLUMN> <OPERATOR> <VALUE>]*"
|
|
1254
|
+
|
|
1255
|
+
Supported columns include:
|
|
1256
|
+
- `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: String fields with full operator support
|
|
1257
|
+
- `status`: String field (=, contains, not_contains only)
|
|
1258
|
+
- `start_time`, `end_time`: DateTime fields (use ISO 8601 format, e.g., "2024-01-01T00:00:00Z")
|
|
1259
|
+
- `input`, `output`: String fields for content (=, contains, not_contains only)
|
|
1260
|
+
- `metadata`: Dictionary field (use dot notation, e.g., "metadata.model")
|
|
1261
|
+
- `feedback_scores`: Numeric field (use dot notation, e.g., "feedback_scores.accuracy")
|
|
1262
|
+
- `tags`: List field (use "contains" operator only)
|
|
1263
|
+
- `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`: Numeric usage fields
|
|
1264
|
+
- `duration`, `number_of_messages`, `total_estimated_cost`: Numeric fields
|
|
1265
|
+
|
|
1266
|
+
Supported operators by column:
|
|
1267
|
+
- `id`, `name`, `created_by`, `thread_id`, `type`, `model`, `provider`: =, !=, contains, not_contains, starts_with, ends_with, >, <
|
|
1268
|
+
- `status`: =, contains, not_contains
|
|
1269
|
+
- `start_time`, `end_time`: =, >, <, >=, <=
|
|
1270
|
+
- `input`, `output`: =, contains, not_contains
|
|
1271
|
+
- `metadata`: =, contains, >, <
|
|
1272
|
+
- `feedback_scores`: =, >, <, >=, <=, is_empty, is_not_empty
|
|
1273
|
+
- `tags`: contains (only)
|
|
1274
|
+
- `usage.total_tokens`, `usage.prompt_tokens`, `usage.completion_tokens`, `duration`, `number_of_messages`, `total_estimated_cost`: =, !=, >, <, >=, <=
|
|
1275
|
+
|
|
1276
|
+
Examples:
|
|
1277
|
+
- `start_time >= "2024-01-01T00:00:00Z"` - Filter by start date
|
|
1278
|
+
- `start_time > "2024-01-01T00:00:00Z" AND start_time < "2024-02-01T00:00:00Z"` - Date range
|
|
1279
|
+
- `input contains "question"` - Filter by input content
|
|
1280
|
+
- `usage.total_tokens > 1000` - Filter by token usage
|
|
1281
|
+
- `feedback_scores.accuracy > 0.8` - Filter by feedback score
|
|
1282
|
+
- `feedback_scores.my_metric is_empty` - Filter spans with empty feedback score
|
|
1283
|
+
- `feedback_scores.my_metric is_not_empty` - Filter spans with non-empty feedback score
|
|
1284
|
+
- `tags contains "production"` - Filter by tag
|
|
1285
|
+
- `metadata.model = "gpt-4"` - Filter by metadata field
|
|
1286
|
+
- `thread_id = "thread_123"` - Filter by thread ID
|
|
1287
|
+
|
|
1288
|
+
If not provided, all spans in the project/trace will be returned up to the limit.
|
|
887
1289
|
max_results: The maximum number of spans to return.
|
|
888
|
-
truncate: Whether to truncate image data stored in input, output or metadata
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
spans: List[span_public.SpanPublic] = []
|
|
1290
|
+
truncate: Whether to truncate image data stored in input, output, or metadata
|
|
1291
|
+
wait_for_at_least: The minimum number of spans to wait for before returning.
|
|
1292
|
+
wait_for_timeout: The timeout for waiting for spans.
|
|
892
1293
|
|
|
893
|
-
|
|
1294
|
+
Raises:
|
|
1295
|
+
exceptions.SearchTimeoutError if wait_for_at_least spans are not found within the specified timeout.
|
|
1296
|
+
"""
|
|
1297
|
+
filters = helpers.parse_filter_expressions(
|
|
1298
|
+
filter_string, parsed_item_class=span_filter_public.SpanFilterPublic
|
|
1299
|
+
)
|
|
894
1300
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
)
|
|
1301
|
+
search_functor = functools.partial(
|
|
1302
|
+
search_helpers.search_spans_with_filters,
|
|
1303
|
+
rest_client=self._rest_client,
|
|
1304
|
+
project_name=project_name or self._project_name,
|
|
1305
|
+
trace_id=trace_id,
|
|
1306
|
+
filters=filters,
|
|
1307
|
+
max_results=max_results,
|
|
1308
|
+
truncate=truncate,
|
|
1309
|
+
)
|
|
905
1310
|
|
|
906
|
-
|
|
907
|
-
|
|
1311
|
+
if wait_for_at_least is None:
|
|
1312
|
+
return search_functor()
|
|
908
1313
|
|
|
909
|
-
|
|
910
|
-
|
|
1314
|
+
# do synchronization with backend if wait_for_at_least is provided until a specific number of spans are found
|
|
1315
|
+
result = search_helpers.search_and_wait_for_done(
|
|
1316
|
+
search_functor=search_functor,
|
|
1317
|
+
wait_for_at_least=wait_for_at_least,
|
|
1318
|
+
wait_for_timeout=wait_for_timeout,
|
|
1319
|
+
sleep_time=5,
|
|
1320
|
+
)
|
|
1321
|
+
if len(result) < wait_for_at_least:
|
|
1322
|
+
raise exceptions.SearchTimeoutError(
|
|
1323
|
+
f"Timeout after {wait_for_timeout} seconds: expected {wait_for_at_least} spans, but only {len(result)} were found."
|
|
1324
|
+
)
|
|
911
1325
|
|
|
912
|
-
return
|
|
1326
|
+
return result
|
|
913
1327
|
|
|
914
1328
|
def get_trace_content(self, id: str) -> trace_public.TracePublic:
|
|
915
1329
|
"""
|
|
@@ -936,7 +1350,7 @@ class Opik:
|
|
|
936
1350
|
Fetches a project by its unique identifier.
|
|
937
1351
|
|
|
938
1352
|
Parameters:
|
|
939
|
-
id (str): project
|
|
1353
|
+
id (str): project id (uuid).
|
|
940
1354
|
|
|
941
1355
|
Returns:
|
|
942
1356
|
project_public.ProjectPublic: pydantic model object with all the data associated with the project found.
|
|
@@ -958,9 +1372,45 @@ class Opik:
|
|
|
958
1372
|
str: URL
|
|
959
1373
|
"""
|
|
960
1374
|
|
|
1375
|
+
dereferenced_workspace = self._workspace
|
|
1376
|
+
if dereferenced_workspace == config.OPIK_WORKSPACE_DEFAULT_NAME:
|
|
1377
|
+
dereferenced_workspace = (
|
|
1378
|
+
self._rest_client.check.get_workspace_name().workspace_name
|
|
1379
|
+
)
|
|
1380
|
+
|
|
961
1381
|
project_name = project_name or self._project_name
|
|
1382
|
+
|
|
962
1383
|
return url_helpers.get_project_url_by_workspace(
|
|
963
|
-
workspace=
|
|
1384
|
+
workspace=dereferenced_workspace, project_name=project_name
|
|
1385
|
+
)
|
|
1386
|
+
|
|
1387
|
+
def get_threads_client(self) -> threads_client.ThreadsClient:
|
|
1388
|
+
"""
|
|
1389
|
+
Creates and provides an instance of the ``ThreadsClient`` tied to the current context.
|
|
1390
|
+
|
|
1391
|
+
The ``ThreadsClient`` can be used to interact with the threads API to manage and interact with conversational threads.
|
|
1392
|
+
|
|
1393
|
+
Returns:
|
|
1394
|
+
ThreadsClient: An instance of ``threads_client.ThreadsClient`` initialized
|
|
1395
|
+
with the current context.
|
|
1396
|
+
"""
|
|
1397
|
+
return threads_client.ThreadsClient(self)
|
|
1398
|
+
|
|
1399
|
+
def get_attachment_client(self) -> attachment_client.AttachmentClient:
|
|
1400
|
+
"""
|
|
1401
|
+
Creates and provides an instance of the ``AttachmentClient`` tied to the current context.
|
|
1402
|
+
|
|
1403
|
+
The ``AttachmentClient`` can be used to interact with the attachments API to retrieve
|
|
1404
|
+
attachment lists, download attachments, and upload attachments for traces and spans.
|
|
1405
|
+
|
|
1406
|
+
Returns:
|
|
1407
|
+
AttachmentClient: An instance of ``attachment.client.AttachmentClient``
|
|
1408
|
+
"""
|
|
1409
|
+
return attachment_client.AttachmentClient(
|
|
1410
|
+
rest_client=self._rest_client,
|
|
1411
|
+
url_override=self._config.url_override,
|
|
1412
|
+
workspace_name=self._workspace,
|
|
1413
|
+
rest_httpx_client=self._httpx_client,
|
|
964
1414
|
)
|
|
965
1415
|
|
|
966
1416
|
def create_prompt(
|
|
@@ -968,55 +1418,303 @@ class Opik:
|
|
|
968
1418
|
name: str,
|
|
969
1419
|
prompt: str,
|
|
970
1420
|
metadata: Optional[Dict[str, Any]] = None,
|
|
971
|
-
|
|
1421
|
+
type: prompt_module.PromptType = prompt_module.PromptType.MUSTACHE,
|
|
1422
|
+
) -> prompt_module.Prompt:
|
|
972
1423
|
"""
|
|
973
|
-
Creates a new prompt with the given name and template.
|
|
974
|
-
If a prompt with the same name already exists, it will create a new version of the existing prompt if the templates differ.
|
|
1424
|
+
Creates a new text prompt with the given name and template.
|
|
1425
|
+
If a text prompt with the same name already exists, it will create a new version of the existing prompt if the templates differ.
|
|
975
1426
|
|
|
976
1427
|
Parameters:
|
|
977
1428
|
name: The name of the prompt.
|
|
978
1429
|
prompt: The template content of the prompt.
|
|
979
1430
|
metadata: Optional metadata to be included in the prompt.
|
|
1431
|
+
type: The template type (MUSTACHE or JINJA2).
|
|
980
1432
|
|
|
981
1433
|
Returns:
|
|
982
1434
|
A Prompt object containing details of the created or retrieved prompt.
|
|
983
1435
|
|
|
984
1436
|
Raises:
|
|
985
|
-
|
|
1437
|
+
PromptTemplateStructureMismatch: If a chat prompt with the same name already exists (template structure is immutable).
|
|
1438
|
+
ApiError: If there is an error during the creation of the prompt.
|
|
986
1439
|
"""
|
|
987
|
-
|
|
988
|
-
|
|
1440
|
+
prompt_client_ = prompt_client.PromptClient(self._rest_client)
|
|
1441
|
+
prompt_version = prompt_client_.create_prompt(
|
|
1442
|
+
name=name, prompt=prompt, metadata=metadata, type=type
|
|
1443
|
+
)
|
|
1444
|
+
return prompt_module.Prompt.from_fern_prompt_version(name, prompt_version)
|
|
1445
|
+
|
|
1446
|
+
def create_chat_prompt(
|
|
1447
|
+
self,
|
|
1448
|
+
name: str,
|
|
1449
|
+
messages: List[Dict[str, Any]],
|
|
1450
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1451
|
+
type: prompt_module.PromptType = prompt_module.PromptType.MUSTACHE,
|
|
1452
|
+
) -> prompt_module.ChatPrompt:
|
|
1453
|
+
"""
|
|
1454
|
+
Creates a new chat prompt with the given name and message templates.
|
|
1455
|
+
If a chat prompt with the same name already exists, it will create a new version if the messages differ.
|
|
1456
|
+
|
|
1457
|
+
Parameters:
|
|
1458
|
+
name: The name of the chat prompt.
|
|
1459
|
+
messages: List of message dictionaries with 'role' and 'content' fields.
|
|
1460
|
+
metadata: Optional metadata to be included in the prompt.
|
|
1461
|
+
type: The template type (MUSTACHE or JINJA2).
|
|
1462
|
+
|
|
1463
|
+
Returns:
|
|
1464
|
+
A ChatPrompt object containing details of the created or retrieved chat prompt.
|
|
1465
|
+
|
|
1466
|
+
Raises:
|
|
1467
|
+
PromptTemplateStructureMismatch: If a text prompt with the same name already exists (template structure is immutable).
|
|
1468
|
+
ApiError: If there is an error during the creation of the prompt.
|
|
1469
|
+
"""
|
|
1470
|
+
return prompt_module.ChatPrompt(
|
|
1471
|
+
name=name, messages=messages, metadata=metadata, type=type
|
|
1472
|
+
)
|
|
989
1473
|
|
|
990
1474
|
def get_prompt(
|
|
991
1475
|
self,
|
|
992
1476
|
name: str,
|
|
993
1477
|
commit: Optional[str] = None,
|
|
994
|
-
) -> Optional[Prompt]:
|
|
1478
|
+
) -> Optional[prompt_module.Prompt]:
|
|
995
1479
|
"""
|
|
996
|
-
Retrieve
|
|
1480
|
+
Retrieve a text prompt by name and optional commit version.
|
|
1481
|
+
|
|
1482
|
+
This method only returns text prompts.
|
|
997
1483
|
|
|
998
1484
|
Parameters:
|
|
999
1485
|
name: The name of the prompt.
|
|
1000
1486
|
commit: An optional commit version of the prompt. If not provided, the latest version is retrieved.
|
|
1001
1487
|
|
|
1002
1488
|
Returns:
|
|
1003
|
-
Prompt: The details of the specified prompt.
|
|
1489
|
+
Prompt: The details of the specified text prompt, or None if not found.
|
|
1490
|
+
|
|
1491
|
+
Raises:
|
|
1492
|
+
PromptTemplateStructureMismatch: If the prompt exists but is a chat prompt (template structure mismatch).
|
|
1004
1493
|
"""
|
|
1005
|
-
|
|
1006
|
-
|
|
1494
|
+
prompt_client_ = prompt_client.PromptClient(self._rest_client)
|
|
1495
|
+
fern_prompt_version = prompt_client_.get_prompt(
|
|
1496
|
+
name=name, commit=commit, raise_if_not_template_structure="text"
|
|
1497
|
+
)
|
|
1007
1498
|
|
|
1008
|
-
|
|
1499
|
+
if fern_prompt_version is None:
|
|
1500
|
+
return None
|
|
1501
|
+
|
|
1502
|
+
return prompt_module.Prompt.from_fern_prompt_version(name, fern_prompt_version)
|
|
1503
|
+
|
|
1504
|
+
def get_chat_prompt(
|
|
1505
|
+
self,
|
|
1506
|
+
name: str,
|
|
1507
|
+
commit: Optional[str] = None,
|
|
1508
|
+
) -> Optional[prompt_module.ChatPrompt]:
|
|
1009
1509
|
"""
|
|
1010
|
-
Retrieve
|
|
1510
|
+
Retrieve a chat prompt by name and optional commit version.
|
|
1511
|
+
|
|
1512
|
+
This method only returns chat prompts.
|
|
1011
1513
|
|
|
1012
1514
|
Parameters:
|
|
1013
1515
|
name: The name of the prompt.
|
|
1516
|
+
commit: An optional commit version of the prompt. If not provided, the latest version is retrieved.
|
|
1517
|
+
|
|
1518
|
+
Returns:
|
|
1519
|
+
ChatPrompt: The details of the specified chat prompt, or None if not found.
|
|
1520
|
+
|
|
1521
|
+
Raises:
|
|
1522
|
+
PromptTemplateStructureMismatch: If the prompt exists but is a text prompt (template structure mismatch).
|
|
1523
|
+
"""
|
|
1524
|
+
prompt_client_ = prompt_client.PromptClient(self._rest_client)
|
|
1525
|
+
fern_prompt_version = prompt_client_.get_prompt(
|
|
1526
|
+
name=name, commit=commit, raise_if_not_template_structure="chat"
|
|
1527
|
+
)
|
|
1528
|
+
|
|
1529
|
+
if fern_prompt_version is None:
|
|
1530
|
+
return None
|
|
1531
|
+
|
|
1532
|
+
return prompt_module.ChatPrompt.from_fern_prompt_version(
|
|
1533
|
+
name, fern_prompt_version
|
|
1534
|
+
)
|
|
1535
|
+
|
|
1536
|
+
def get_prompt_history(self, name: str) -> List[prompt_module.Prompt]:
|
|
1537
|
+
"""
|
|
1538
|
+
Retrieve all text prompt versions history for a given prompt name.
|
|
1539
|
+
|
|
1540
|
+
Parameters:
|
|
1541
|
+
name: The name of the prompt.
|
|
1542
|
+
|
|
1543
|
+
Returns:
|
|
1544
|
+
List[Prompt]: A list of text Prompt instances for the given name, or an empty list if not found.
|
|
1545
|
+
|
|
1546
|
+
Raises:
|
|
1547
|
+
PromptTemplateStructureMismatch: If the prompt exists but is a chat prompt (template structure mismatch).
|
|
1548
|
+
"""
|
|
1549
|
+
prompt_client_ = prompt_client.PromptClient(self._rest_client)
|
|
1550
|
+
|
|
1551
|
+
# First, validate that this is a text prompt by trying to get the latest version
|
|
1552
|
+
# Let PromptTemplateStructureMismatch exception propagate - this is a hard error
|
|
1553
|
+
latest_version = prompt_client_.get_prompt(
|
|
1554
|
+
name=name, raise_if_not_template_structure="text"
|
|
1555
|
+
)
|
|
1556
|
+
|
|
1557
|
+
if latest_version is None:
|
|
1558
|
+
return []
|
|
1559
|
+
|
|
1560
|
+
# Now get all versions (we know it's a text prompt)
|
|
1561
|
+
fern_prompt_versions = prompt_client_.get_all_prompt_versions(name=name)
|
|
1562
|
+
|
|
1563
|
+
result = [
|
|
1564
|
+
prompt_module.Prompt.from_fern_prompt_version(name, version)
|
|
1565
|
+
for version in fern_prompt_versions
|
|
1566
|
+
]
|
|
1567
|
+
return result
|
|
1568
|
+
|
|
1569
|
+
def get_chat_prompt_history(self, name: str) -> List[prompt_module.ChatPrompt]:
|
|
1570
|
+
"""
|
|
1571
|
+
Retrieve all chat prompt versions history for a given prompt name.
|
|
1572
|
+
|
|
1573
|
+
Parameters:
|
|
1574
|
+
name: The name of the prompt.
|
|
1575
|
+
|
|
1576
|
+
Returns:
|
|
1577
|
+
List[ChatPrompt]: A list of ChatPrompt instances for the given name, or an empty list if not found.
|
|
1578
|
+
|
|
1579
|
+
Raises:
|
|
1580
|
+
PromptTemplateStructureMismatch: If the prompt exists but is a text prompt (template structure mismatch).
|
|
1581
|
+
"""
|
|
1582
|
+
prompt_client_ = prompt_client.PromptClient(self._rest_client)
|
|
1583
|
+
|
|
1584
|
+
# First, validate that this is a chat prompt by trying to get the latest version
|
|
1585
|
+
# Let PromptTemplateStructureMismatch exception propagate - this is a hard error
|
|
1586
|
+
latest_version = prompt_client_.get_prompt(
|
|
1587
|
+
name=name, raise_if_not_template_structure="chat"
|
|
1588
|
+
)
|
|
1589
|
+
|
|
1590
|
+
if latest_version is None:
|
|
1591
|
+
return []
|
|
1592
|
+
|
|
1593
|
+
# Now get all versions (we know it's a chat prompt)
|
|
1594
|
+
fern_prompt_versions = prompt_client_.get_all_prompt_versions(name=name)
|
|
1595
|
+
|
|
1596
|
+
result = [
|
|
1597
|
+
prompt_module.ChatPrompt.from_fern_prompt_version(name, version)
|
|
1598
|
+
for version in fern_prompt_versions
|
|
1599
|
+
]
|
|
1600
|
+
return result
|
|
1601
|
+
|
|
1602
|
+
def get_all_prompts(self, name: str) -> List[prompt_module.Prompt]:
|
|
1603
|
+
"""
|
|
1604
|
+
DEPRECATED: Please use Opik.get_prompt_history() instead.
|
|
1605
|
+
Retrieve all the prompt versions history for a given prompt name.
|
|
1606
|
+
|
|
1607
|
+
Parameters:
|
|
1608
|
+
name: The name of the prompt.
|
|
1609
|
+
|
|
1610
|
+
Returns:
|
|
1611
|
+
List[prompt_module.Prompt]: A list of Prompt instances for the given name.
|
|
1612
|
+
"""
|
|
1613
|
+
LOGGER.warning(
|
|
1614
|
+
"Opik.get_all_prompts() is deprecated. Please use Opik.get_prompt_history() instead."
|
|
1615
|
+
)
|
|
1616
|
+
return self.get_prompt_history(name)
|
|
1617
|
+
|
|
1618
|
+
def search_prompts(
|
|
1619
|
+
self, filter_string: Optional[str] = None
|
|
1620
|
+
) -> List[Union[prompt_module.Prompt, prompt_module.ChatPrompt]]:
|
|
1621
|
+
"""
|
|
1622
|
+
Retrieve the latest prompt versions (both string and chat prompts) for the given search parameters.
|
|
1623
|
+
|
|
1624
|
+
Parameters:
|
|
1625
|
+
filter_string: A filter string to narrow down the search using Opik Query Language (OQL).
|
|
1626
|
+
The format is: "<COLUMN> <OPERATOR> <VALUE> [AND <COLUMN> <OPERATOR> <VALUE>]*"
|
|
1627
|
+
|
|
1628
|
+
Supported columns include:
|
|
1629
|
+
- `id`, `name`: String fields
|
|
1630
|
+
- `tags`: List field (use "contains" operator only)
|
|
1631
|
+
- `created_by`: String field
|
|
1632
|
+
- `template_structure`: String field ("string" or "chat")
|
|
1633
|
+
|
|
1634
|
+
Supported operators by column:
|
|
1635
|
+
- `id`: =, !=, contains, not_contains, starts_with, ends_with, >, <
|
|
1636
|
+
- `name`: =, !=, contains, not_contains, starts_with, ends_with, >, <
|
|
1637
|
+
- `created_by`: =, !=, contains, not_contains, starts_with, ends_with, >, <
|
|
1638
|
+
- `template_structure`: =, !=
|
|
1639
|
+
- `tags`: contains (only)
|
|
1640
|
+
|
|
1641
|
+
Examples:
|
|
1642
|
+
- `tags contains "alpha"` - Filter by tag
|
|
1643
|
+
- `tags contains "alpha" AND tags contains "beta"` - Filter by multiple tags
|
|
1644
|
+
- `name contains "summary"` - Filter by name substring
|
|
1645
|
+
- `created_by = "user@example.com"` - Filter by creator
|
|
1646
|
+
- `id starts_with "prompt_"` - Filter by ID prefix
|
|
1647
|
+
- `template_structure = "text"` - Only text prompts
|
|
1648
|
+
- `template_structure = "chat"` - Only chat prompts
|
|
1649
|
+
|
|
1650
|
+
If not provided, all prompts (both text and chat) will be returned.
|
|
1651
|
+
|
|
1652
|
+
Returns:
|
|
1653
|
+
List[Union[Prompt, ChatPrompt]]: A list of Prompt and/or ChatPrompt instances found.
|
|
1654
|
+
"""
|
|
1655
|
+
oql = opik_query_language.OpikQueryLanguage(filter_string or "")
|
|
1656
|
+
parsed_filters = oql.get_filter_expressions()
|
|
1657
|
+
|
|
1658
|
+
prompt_client_ = prompt_client.PromptClient(self._rest_client)
|
|
1659
|
+
search_results = prompt_client_.search_prompts(parsed_filters=parsed_filters)
|
|
1660
|
+
|
|
1661
|
+
# Convert to Prompt or ChatPrompt objects based on template_structure
|
|
1662
|
+
prompts: List[Union[prompt_module.Prompt, prompt_module.ChatPrompt]] = []
|
|
1663
|
+
for result in search_results:
|
|
1664
|
+
if result.template_structure == "chat":
|
|
1665
|
+
prompts.append(
|
|
1666
|
+
prompt_module.ChatPrompt.from_fern_prompt_version(
|
|
1667
|
+
result.name, result.prompt_version_detail
|
|
1668
|
+
)
|
|
1669
|
+
)
|
|
1670
|
+
else:
|
|
1671
|
+
prompts.append(
|
|
1672
|
+
prompt_module.Prompt.from_fern_prompt_version(
|
|
1673
|
+
result.name, result.prompt_version_detail
|
|
1674
|
+
)
|
|
1675
|
+
)
|
|
1676
|
+
|
|
1677
|
+
return prompts
|
|
1678
|
+
|
|
1679
|
+
def create_optimization(
|
|
1680
|
+
self,
|
|
1681
|
+
dataset_name: str,
|
|
1682
|
+
objective_name: str,
|
|
1683
|
+
name: Optional[str] = None,
|
|
1684
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1685
|
+
optimization_id: Optional[str] = None,
|
|
1686
|
+
) -> optimization.Optimization:
|
|
1687
|
+
id = optimization_id or id_helpers.generate_id()
|
|
1688
|
+
|
|
1689
|
+
self._rest_client.optimizations.create_optimization(
|
|
1690
|
+
id=id,
|
|
1691
|
+
name=name,
|
|
1692
|
+
dataset_name=dataset_name,
|
|
1693
|
+
objective_name=objective_name,
|
|
1694
|
+
status="running",
|
|
1695
|
+
metadata=metadata,
|
|
1696
|
+
)
|
|
1697
|
+
|
|
1698
|
+
optimization_client = optimization.Optimization(
|
|
1699
|
+
id=id, rest_client=self._rest_client
|
|
1700
|
+
)
|
|
1701
|
+
return optimization_client
|
|
1702
|
+
|
|
1703
|
+
def delete_optimizations(self, ids: List[str]) -> None:
|
|
1704
|
+
self._rest_client.optimizations.delete_optimizations_by_id(ids=ids)
|
|
1705
|
+
|
|
1706
|
+
def get_optimization_by_id(self, id: str) -> optimization.Optimization:
|
|
1707
|
+
_ = self._rest_client.optimizations.get_optimization_by_id(id)
|
|
1708
|
+
return optimization.Optimization(id=id, rest_client=self._rest_client)
|
|
1709
|
+
|
|
1710
|
+
def get_experiments_client(self) -> experiments_client.ExperimentsClient:
|
|
1711
|
+
"""
|
|
1712
|
+
Retrieves an instance of `ExperimentsClient`.
|
|
1014
1713
|
|
|
1015
1714
|
Returns:
|
|
1016
|
-
|
|
1715
|
+
An instance of the ExperimentsClient initialized with a cached REST client.
|
|
1017
1716
|
"""
|
|
1018
|
-
|
|
1019
|
-
return prompt_client.get_all_prompts(name=name)
|
|
1717
|
+
return experiments_client.ExperimentsClient(self._rest_client)
|
|
1020
1718
|
|
|
1021
1719
|
|
|
1022
1720
|
@functools.lru_cache()
|