opik 1.8.39__py3-none-any.whl → 1.9.71__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opik/__init__.py +19 -3
- opik/anonymizer/__init__.py +5 -0
- opik/anonymizer/anonymizer.py +12 -0
- opik/anonymizer/factory.py +80 -0
- opik/anonymizer/recursive_anonymizer.py +64 -0
- opik/anonymizer/rules.py +56 -0
- opik/anonymizer/rules_anonymizer.py +35 -0
- opik/api_objects/attachment/attachment_context.py +36 -0
- opik/api_objects/attachment/attachments_extractor.py +153 -0
- opik/api_objects/attachment/client.py +1 -0
- opik/api_objects/attachment/converters.py +2 -0
- opik/api_objects/attachment/decoder.py +18 -0
- opik/api_objects/attachment/decoder_base64.py +83 -0
- opik/api_objects/attachment/decoder_helpers.py +137 -0
- opik/api_objects/data_helpers.py +79 -0
- opik/api_objects/dataset/dataset.py +64 -4
- opik/api_objects/dataset/rest_operations.py +11 -2
- opik/api_objects/experiment/experiment.py +57 -57
- opik/api_objects/experiment/experiment_item.py +2 -1
- opik/api_objects/experiment/experiments_client.py +64 -0
- opik/api_objects/experiment/helpers.py +35 -11
- opik/api_objects/experiment/rest_operations.py +65 -5
- opik/api_objects/helpers.py +8 -5
- opik/api_objects/local_recording.py +81 -0
- opik/api_objects/opik_client.py +600 -108
- opik/api_objects/opik_query_language.py +39 -5
- opik/api_objects/prompt/__init__.py +12 -2
- opik/api_objects/prompt/base_prompt.py +69 -0
- opik/api_objects/prompt/base_prompt_template.py +29 -0
- opik/api_objects/prompt/chat/__init__.py +1 -0
- opik/api_objects/prompt/chat/chat_prompt.py +210 -0
- opik/api_objects/prompt/chat/chat_prompt_template.py +350 -0
- opik/api_objects/prompt/chat/content_renderer_registry.py +203 -0
- opik/api_objects/prompt/client.py +189 -47
- opik/api_objects/prompt/text/__init__.py +1 -0
- opik/api_objects/prompt/text/prompt.py +174 -0
- opik/api_objects/prompt/{prompt_template.py → text/prompt_template.py} +10 -6
- opik/api_objects/prompt/types.py +23 -0
- opik/api_objects/search_helpers.py +89 -0
- opik/api_objects/span/span_data.py +35 -25
- opik/api_objects/threads/threads_client.py +39 -5
- opik/api_objects/trace/trace_client.py +52 -2
- opik/api_objects/trace/trace_data.py +15 -24
- opik/api_objects/validation_helpers.py +3 -3
- opik/cli/__init__.py +5 -0
- opik/cli/__main__.py +6 -0
- opik/cli/configure.py +66 -0
- opik/cli/exports/__init__.py +131 -0
- opik/cli/exports/dataset.py +278 -0
- opik/cli/exports/experiment.py +784 -0
- opik/cli/exports/project.py +685 -0
- opik/cli/exports/prompt.py +578 -0
- opik/cli/exports/utils.py +406 -0
- opik/cli/harbor.py +39 -0
- opik/cli/healthcheck.py +21 -0
- opik/cli/imports/__init__.py +439 -0
- opik/cli/imports/dataset.py +143 -0
- opik/cli/imports/experiment.py +1192 -0
- opik/cli/imports/project.py +262 -0
- opik/cli/imports/prompt.py +177 -0
- opik/cli/imports/utils.py +280 -0
- opik/cli/main.py +49 -0
- opik/cli/proxy.py +93 -0
- opik/cli/usage_report/__init__.py +16 -0
- opik/cli/usage_report/charts.py +783 -0
- opik/cli/usage_report/cli.py +274 -0
- opik/cli/usage_report/constants.py +9 -0
- opik/cli/usage_report/extraction.py +749 -0
- opik/cli/usage_report/pdf.py +244 -0
- opik/cli/usage_report/statistics.py +78 -0
- opik/cli/usage_report/utils.py +235 -0
- opik/config.py +13 -7
- opik/configurator/configure.py +17 -0
- opik/datetime_helpers.py +12 -0
- opik/decorator/arguments_helpers.py +9 -1
- opik/decorator/base_track_decorator.py +205 -133
- opik/decorator/context_manager/span_context_manager.py +123 -0
- opik/decorator/context_manager/trace_context_manager.py +84 -0
- opik/decorator/opik_args/__init__.py +13 -0
- opik/decorator/opik_args/api_classes.py +71 -0
- opik/decorator/opik_args/helpers.py +120 -0
- opik/decorator/span_creation_handler.py +25 -6
- opik/dict_utils.py +3 -3
- opik/evaluation/__init__.py +13 -2
- opik/evaluation/engine/engine.py +272 -75
- opik/evaluation/engine/evaluation_tasks_executor.py +6 -3
- opik/evaluation/engine/helpers.py +31 -6
- opik/evaluation/engine/metrics_evaluator.py +237 -0
- opik/evaluation/evaluation_result.py +168 -2
- opik/evaluation/evaluator.py +533 -62
- opik/evaluation/metrics/__init__.py +103 -4
- opik/evaluation/metrics/aggregated_metric.py +35 -6
- opik/evaluation/metrics/base_metric.py +1 -1
- opik/evaluation/metrics/conversation/__init__.py +48 -0
- opik/evaluation/metrics/conversation/conversation_thread_metric.py +56 -2
- opik/evaluation/metrics/conversation/g_eval_wrappers.py +19 -0
- opik/evaluation/metrics/conversation/helpers.py +14 -15
- opik/evaluation/metrics/conversation/heuristics/__init__.py +14 -0
- opik/evaluation/metrics/conversation/heuristics/degeneration/__init__.py +3 -0
- opik/evaluation/metrics/conversation/heuristics/degeneration/metric.py +189 -0
- opik/evaluation/metrics/conversation/heuristics/degeneration/phrases.py +12 -0
- opik/evaluation/metrics/conversation/heuristics/knowledge_retention/__init__.py +3 -0
- opik/evaluation/metrics/conversation/heuristics/knowledge_retention/metric.py +172 -0
- opik/evaluation/metrics/conversation/llm_judges/__init__.py +32 -0
- opik/evaluation/metrics/conversation/{conversational_coherence → llm_judges/conversational_coherence}/metric.py +22 -17
- opik/evaluation/metrics/conversation/{conversational_coherence → llm_judges/conversational_coherence}/templates.py +1 -1
- opik/evaluation/metrics/conversation/llm_judges/g_eval_wrappers.py +442 -0
- opik/evaluation/metrics/conversation/{session_completeness → llm_judges/session_completeness}/metric.py +13 -7
- opik/evaluation/metrics/conversation/{session_completeness → llm_judges/session_completeness}/templates.py +1 -1
- opik/evaluation/metrics/conversation/llm_judges/user_frustration/__init__.py +0 -0
- opik/evaluation/metrics/conversation/{user_frustration → llm_judges/user_frustration}/metric.py +21 -14
- opik/evaluation/metrics/conversation/{user_frustration → llm_judges/user_frustration}/templates.py +1 -1
- opik/evaluation/metrics/conversation/types.py +4 -5
- opik/evaluation/metrics/conversation_types.py +9 -0
- opik/evaluation/metrics/heuristics/bertscore.py +107 -0
- opik/evaluation/metrics/heuristics/bleu.py +35 -15
- opik/evaluation/metrics/heuristics/chrf.py +127 -0
- opik/evaluation/metrics/heuristics/contains.py +47 -11
- opik/evaluation/metrics/heuristics/distribution_metrics.py +331 -0
- opik/evaluation/metrics/heuristics/gleu.py +113 -0
- opik/evaluation/metrics/heuristics/language_adherence.py +123 -0
- opik/evaluation/metrics/heuristics/meteor.py +119 -0
- opik/evaluation/metrics/heuristics/prompt_injection.py +150 -0
- opik/evaluation/metrics/heuristics/readability.py +129 -0
- opik/evaluation/metrics/heuristics/rouge.py +26 -9
- opik/evaluation/metrics/heuristics/spearman.py +88 -0
- opik/evaluation/metrics/heuristics/tone.py +155 -0
- opik/evaluation/metrics/heuristics/vader_sentiment.py +77 -0
- opik/evaluation/metrics/llm_judges/answer_relevance/metric.py +20 -5
- opik/evaluation/metrics/llm_judges/context_precision/metric.py +20 -6
- opik/evaluation/metrics/llm_judges/context_recall/metric.py +20 -6
- opik/evaluation/metrics/llm_judges/g_eval/__init__.py +5 -0
- opik/evaluation/metrics/llm_judges/g_eval/metric.py +219 -68
- opik/evaluation/metrics/llm_judges/g_eval/parser.py +102 -52
- opik/evaluation/metrics/llm_judges/g_eval/presets.py +209 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/__init__.py +36 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/agent_assessment.py +77 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/bias_classifier.py +181 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/compliance_risk.py +41 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/prompt_uncertainty.py +41 -0
- opik/evaluation/metrics/llm_judges/g_eval_presets/qa_suite.py +146 -0
- opik/evaluation/metrics/llm_judges/hallucination/metric.py +16 -3
- opik/evaluation/metrics/llm_judges/llm_juries/__init__.py +3 -0
- opik/evaluation/metrics/llm_judges/llm_juries/metric.py +76 -0
- opik/evaluation/metrics/llm_judges/moderation/metric.py +16 -4
- opik/evaluation/metrics/llm_judges/structure_output_compliance/__init__.py +0 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/metric.py +144 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/parser.py +79 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/schema.py +15 -0
- opik/evaluation/metrics/llm_judges/structure_output_compliance/template.py +50 -0
- opik/evaluation/metrics/llm_judges/syc_eval/__init__.py +0 -0
- opik/evaluation/metrics/llm_judges/syc_eval/metric.py +252 -0
- opik/evaluation/metrics/llm_judges/syc_eval/parser.py +82 -0
- opik/evaluation/metrics/llm_judges/syc_eval/template.py +155 -0
- opik/evaluation/metrics/llm_judges/trajectory_accuracy/metric.py +20 -5
- opik/evaluation/metrics/llm_judges/usefulness/metric.py +16 -4
- opik/evaluation/metrics/ragas_metric.py +43 -23
- opik/evaluation/models/__init__.py +8 -0
- opik/evaluation/models/base_model.py +107 -1
- opik/evaluation/models/langchain/langchain_chat_model.py +15 -7
- opik/evaluation/models/langchain/message_converters.py +97 -15
- opik/evaluation/models/litellm/litellm_chat_model.py +156 -29
- opik/evaluation/models/litellm/util.py +125 -0
- opik/evaluation/models/litellm/warning_filters.py +16 -4
- opik/evaluation/models/model_capabilities.py +187 -0
- opik/evaluation/models/models_factory.py +25 -3
- opik/evaluation/preprocessing.py +92 -0
- opik/evaluation/report.py +70 -12
- opik/evaluation/rest_operations.py +49 -45
- opik/evaluation/samplers/__init__.py +4 -0
- opik/evaluation/samplers/base_dataset_sampler.py +40 -0
- opik/evaluation/samplers/random_dataset_sampler.py +48 -0
- opik/evaluation/score_statistics.py +66 -0
- opik/evaluation/scorers/__init__.py +4 -0
- opik/evaluation/scorers/scorer_function.py +55 -0
- opik/evaluation/scorers/scorer_wrapper_metric.py +130 -0
- opik/evaluation/test_case.py +3 -2
- opik/evaluation/test_result.py +1 -0
- opik/evaluation/threads/evaluator.py +31 -3
- opik/evaluation/threads/helpers.py +3 -2
- opik/evaluation/types.py +9 -1
- opik/exceptions.py +33 -0
- opik/file_upload/file_uploader.py +13 -0
- opik/file_upload/upload_options.py +2 -0
- opik/hooks/__init__.py +23 -0
- opik/hooks/anonymizer_hook.py +36 -0
- opik/hooks/httpx_client_hook.py +112 -0
- opik/httpx_client.py +12 -9
- opik/id_helpers.py +18 -0
- opik/integrations/adk/graph/subgraph_edges_builders.py +1 -2
- opik/integrations/adk/helpers.py +16 -7
- opik/integrations/adk/legacy_opik_tracer.py +7 -4
- opik/integrations/adk/opik_tracer.py +14 -1
- opik/integrations/adk/patchers/adk_otel_tracer/opik_adk_otel_tracer.py +7 -3
- opik/integrations/adk/recursive_callback_injector.py +4 -7
- opik/integrations/bedrock/converse/__init__.py +0 -0
- opik/integrations/bedrock/converse/chunks_aggregator.py +188 -0
- opik/integrations/bedrock/{converse_decorator.py → converse/converse_decorator.py} +4 -3
- opik/integrations/bedrock/invoke_agent_decorator.py +5 -4
- opik/integrations/bedrock/invoke_model/__init__.py +0 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/__init__.py +78 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/api.py +45 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/base.py +23 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/claude.py +121 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/format_detector.py +107 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/llama.py +108 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/mistral.py +118 -0
- opik/integrations/bedrock/invoke_model/chunks_aggregator/nova.py +99 -0
- opik/integrations/bedrock/invoke_model/invoke_model_decorator.py +178 -0
- opik/integrations/bedrock/invoke_model/response_types.py +34 -0
- opik/integrations/bedrock/invoke_model/stream_wrappers.py +122 -0
- opik/integrations/bedrock/invoke_model/usage_converters.py +87 -0
- opik/integrations/bedrock/invoke_model/usage_extraction.py +108 -0
- opik/integrations/bedrock/opik_tracker.py +42 -4
- opik/integrations/bedrock/types.py +19 -0
- opik/integrations/crewai/crewai_decorator.py +8 -51
- opik/integrations/crewai/opik_tracker.py +31 -10
- opik/integrations/crewai/patchers/__init__.py +5 -0
- opik/integrations/crewai/patchers/flow.py +118 -0
- opik/integrations/crewai/patchers/litellm_completion.py +30 -0
- opik/integrations/crewai/patchers/llm_client.py +207 -0
- opik/integrations/dspy/callback.py +80 -17
- opik/integrations/dspy/parsers.py +168 -0
- opik/integrations/harbor/__init__.py +17 -0
- opik/integrations/harbor/experiment_service.py +269 -0
- opik/integrations/harbor/opik_tracker.py +528 -0
- opik/integrations/haystack/opik_connector.py +2 -2
- opik/integrations/haystack/opik_tracer.py +3 -7
- opik/integrations/langchain/__init__.py +3 -1
- opik/integrations/langchain/helpers.py +96 -0
- opik/integrations/langchain/langgraph_async_context_bridge.py +131 -0
- opik/integrations/langchain/langgraph_tracer_injector.py +88 -0
- opik/integrations/langchain/opik_encoder_extension.py +1 -1
- opik/integrations/langchain/opik_tracer.py +474 -229
- opik/integrations/litellm/__init__.py +5 -0
- opik/integrations/litellm/completion_chunks_aggregator.py +115 -0
- opik/integrations/litellm/litellm_completion_decorator.py +242 -0
- opik/integrations/litellm/opik_tracker.py +43 -0
- opik/integrations/litellm/stream_patchers.py +151 -0
- opik/integrations/llama_index/callback.py +146 -107
- opik/integrations/openai/agents/opik_tracing_processor.py +1 -2
- opik/integrations/openai/openai_chat_completions_decorator.py +2 -16
- opik/integrations/openai/opik_tracker.py +1 -1
- opik/integrations/sagemaker/auth.py +5 -1
- opik/llm_usage/google_usage.py +3 -1
- opik/llm_usage/opik_usage.py +7 -8
- opik/llm_usage/opik_usage_factory.py +4 -2
- opik/logging_messages.py +6 -0
- opik/message_processing/batching/base_batcher.py +14 -21
- opik/message_processing/batching/batch_manager.py +22 -10
- opik/message_processing/batching/batch_manager_constuctors.py +10 -0
- opik/message_processing/batching/batchers.py +59 -27
- opik/message_processing/batching/flushing_thread.py +0 -3
- opik/message_processing/emulation/__init__.py +0 -0
- opik/message_processing/emulation/emulator_message_processor.py +578 -0
- opik/message_processing/emulation/local_emulator_message_processor.py +140 -0
- opik/message_processing/emulation/models.py +162 -0
- opik/message_processing/encoder_helpers.py +79 -0
- opik/message_processing/messages.py +56 -1
- opik/message_processing/preprocessing/__init__.py +0 -0
- opik/message_processing/preprocessing/attachments_preprocessor.py +70 -0
- opik/message_processing/preprocessing/batching_preprocessor.py +53 -0
- opik/message_processing/preprocessing/constants.py +1 -0
- opik/message_processing/preprocessing/file_upload_preprocessor.py +38 -0
- opik/message_processing/preprocessing/preprocessor.py +36 -0
- opik/message_processing/processors/__init__.py +0 -0
- opik/message_processing/processors/attachments_extraction_processor.py +146 -0
- opik/message_processing/processors/message_processors.py +92 -0
- opik/message_processing/processors/message_processors_chain.py +96 -0
- opik/message_processing/{message_processors.py → processors/online_message_processor.py} +85 -29
- opik/message_processing/queue_consumer.py +9 -3
- opik/message_processing/streamer.py +71 -33
- opik/message_processing/streamer_constructors.py +43 -10
- opik/opik_context.py +16 -4
- opik/plugins/pytest/hooks.py +5 -3
- opik/rest_api/__init__.py +346 -15
- opik/rest_api/alerts/__init__.py +7 -0
- opik/rest_api/alerts/client.py +667 -0
- opik/rest_api/alerts/raw_client.py +1015 -0
- opik/rest_api/alerts/types/__init__.py +7 -0
- opik/rest_api/alerts/types/get_webhook_examples_request_alert_type.py +5 -0
- opik/rest_api/annotation_queues/__init__.py +4 -0
- opik/rest_api/annotation_queues/client.py +668 -0
- opik/rest_api/annotation_queues/raw_client.py +1019 -0
- opik/rest_api/automation_rule_evaluators/client.py +34 -2
- opik/rest_api/automation_rule_evaluators/raw_client.py +24 -0
- opik/rest_api/client.py +15 -0
- opik/rest_api/dashboards/__init__.py +4 -0
- opik/rest_api/dashboards/client.py +462 -0
- opik/rest_api/dashboards/raw_client.py +648 -0
- opik/rest_api/datasets/client.py +1310 -44
- opik/rest_api/datasets/raw_client.py +2269 -358
- opik/rest_api/experiments/__init__.py +2 -2
- opik/rest_api/experiments/client.py +191 -5
- opik/rest_api/experiments/raw_client.py +301 -7
- opik/rest_api/experiments/types/__init__.py +4 -1
- opik/rest_api/experiments/types/experiment_update_status.py +5 -0
- opik/rest_api/experiments/types/experiment_update_type.py +5 -0
- opik/rest_api/experiments/types/experiment_write_status.py +5 -0
- opik/rest_api/feedback_definitions/types/find_feedback_definitions_request_type.py +1 -1
- opik/rest_api/llm_provider_key/client.py +20 -0
- opik/rest_api/llm_provider_key/raw_client.py +20 -0
- opik/rest_api/llm_provider_key/types/provider_api_key_write_provider.py +1 -1
- opik/rest_api/manual_evaluation/__init__.py +4 -0
- opik/rest_api/manual_evaluation/client.py +347 -0
- opik/rest_api/manual_evaluation/raw_client.py +543 -0
- opik/rest_api/optimizations/client.py +145 -9
- opik/rest_api/optimizations/raw_client.py +237 -13
- opik/rest_api/optimizations/types/optimization_update_status.py +3 -1
- opik/rest_api/prompts/__init__.py +2 -2
- opik/rest_api/prompts/client.py +227 -6
- opik/rest_api/prompts/raw_client.py +331 -2
- opik/rest_api/prompts/types/__init__.py +3 -1
- opik/rest_api/prompts/types/create_prompt_version_detail_template_structure.py +5 -0
- opik/rest_api/prompts/types/prompt_write_template_structure.py +5 -0
- opik/rest_api/spans/__init__.py +0 -2
- opik/rest_api/spans/client.py +238 -76
- opik/rest_api/spans/raw_client.py +307 -95
- opik/rest_api/spans/types/__init__.py +0 -2
- opik/rest_api/traces/client.py +572 -161
- opik/rest_api/traces/raw_client.py +736 -229
- opik/rest_api/types/__init__.py +352 -17
- opik/rest_api/types/aggregation_data.py +1 -0
- opik/rest_api/types/alert.py +33 -0
- opik/rest_api/types/alert_alert_type.py +5 -0
- opik/rest_api/types/alert_page_public.py +24 -0
- opik/rest_api/types/alert_public.py +33 -0
- opik/rest_api/types/alert_public_alert_type.py +5 -0
- opik/rest_api/types/alert_trigger.py +27 -0
- opik/rest_api/types/alert_trigger_config.py +28 -0
- opik/rest_api/types/alert_trigger_config_public.py +28 -0
- opik/rest_api/types/alert_trigger_config_public_type.py +10 -0
- opik/rest_api/types/alert_trigger_config_type.py +10 -0
- opik/rest_api/types/alert_trigger_config_write.py +22 -0
- opik/rest_api/types/alert_trigger_config_write_type.py +10 -0
- opik/rest_api/types/alert_trigger_event_type.py +19 -0
- opik/rest_api/types/alert_trigger_public.py +27 -0
- opik/rest_api/types/alert_trigger_public_event_type.py +19 -0
- opik/rest_api/types/alert_trigger_write.py +23 -0
- opik/rest_api/types/alert_trigger_write_event_type.py +19 -0
- opik/rest_api/types/alert_write.py +28 -0
- opik/rest_api/types/alert_write_alert_type.py +5 -0
- opik/rest_api/types/annotation_queue.py +42 -0
- opik/rest_api/types/annotation_queue_batch.py +27 -0
- opik/rest_api/types/annotation_queue_item_ids.py +19 -0
- opik/rest_api/types/annotation_queue_page_public.py +28 -0
- opik/rest_api/types/annotation_queue_public.py +38 -0
- opik/rest_api/types/annotation_queue_public_scope.py +5 -0
- opik/rest_api/types/annotation_queue_reviewer.py +20 -0
- opik/rest_api/types/annotation_queue_reviewer_public.py +20 -0
- opik/rest_api/types/annotation_queue_scope.py +5 -0
- opik/rest_api/types/annotation_queue_write.py +31 -0
- opik/rest_api/types/annotation_queue_write_scope.py +5 -0
- opik/rest_api/types/audio_url.py +19 -0
- opik/rest_api/types/audio_url_public.py +19 -0
- opik/rest_api/types/audio_url_write.py +19 -0
- opik/rest_api/types/automation_rule_evaluator.py +62 -2
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_llm_as_judge_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_object_object_public.py +155 -0
- opik/rest_api/types/automation_rule_evaluator_page_public.py +3 -2
- opik/rest_api/types/automation_rule_evaluator_public.py +57 -2
- opik/rest_api/types/automation_rule_evaluator_span_llm_as_judge.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_llm_as_judge_public.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_llm_as_judge_write.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python_public.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_span_user_defined_metric_python_write.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_llm_as_judge_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_trace_thread_user_defined_metric_python_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update.py +51 -1
- opik/rest_api/types/automation_rule_evaluator_update_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update_span_llm_as_judge.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_update_span_user_defined_metric_python.py +22 -0
- opik/rest_api/types/automation_rule_evaluator_update_trace_thread_llm_as_judge.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update_trace_thread_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_update_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python_public.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_user_defined_metric_python_write.py +2 -0
- opik/rest_api/types/automation_rule_evaluator_write.py +51 -1
- opik/rest_api/types/boolean_feedback_definition.py +25 -0
- opik/rest_api/types/boolean_feedback_definition_create.py +20 -0
- opik/rest_api/types/boolean_feedback_definition_public.py +25 -0
- opik/rest_api/types/boolean_feedback_definition_update.py +20 -0
- opik/rest_api/types/boolean_feedback_detail.py +29 -0
- opik/rest_api/types/boolean_feedback_detail_create.py +29 -0
- opik/rest_api/types/boolean_feedback_detail_public.py +29 -0
- opik/rest_api/types/boolean_feedback_detail_update.py +29 -0
- opik/rest_api/types/dashboard_page_public.py +24 -0
- opik/rest_api/types/dashboard_public.py +30 -0
- opik/rest_api/types/dataset.py +4 -0
- opik/rest_api/types/dataset_expansion.py +42 -0
- opik/rest_api/types/dataset_expansion_response.py +39 -0
- opik/rest_api/types/dataset_item.py +2 -0
- opik/rest_api/types/dataset_item_changes_public.py +5 -0
- opik/rest_api/types/dataset_item_compare.py +2 -0
- opik/rest_api/types/dataset_item_filter.py +27 -0
- opik/rest_api/types/dataset_item_filter_operator.py +21 -0
- opik/rest_api/types/dataset_item_page_compare.py +5 -0
- opik/rest_api/types/dataset_item_page_public.py +5 -0
- opik/rest_api/types/dataset_item_public.py +2 -0
- opik/rest_api/types/dataset_item_update.py +39 -0
- opik/rest_api/types/dataset_item_write.py +1 -0
- opik/rest_api/types/dataset_public.py +4 -0
- opik/rest_api/types/dataset_public_status.py +5 -0
- opik/rest_api/types/dataset_status.py +5 -0
- opik/rest_api/types/dataset_version_diff.py +22 -0
- opik/rest_api/types/dataset_version_diff_stats.py +24 -0
- opik/rest_api/types/dataset_version_page_public.py +23 -0
- opik/rest_api/types/dataset_version_public.py +59 -0
- opik/rest_api/types/dataset_version_summary.py +46 -0
- opik/rest_api/types/dataset_version_summary_public.py +46 -0
- opik/rest_api/types/experiment.py +7 -2
- opik/rest_api/types/experiment_group_response.py +2 -0
- opik/rest_api/types/experiment_public.py +7 -2
- opik/rest_api/types/experiment_public_status.py +5 -0
- opik/rest_api/types/experiment_score.py +20 -0
- opik/rest_api/types/experiment_score_public.py +20 -0
- opik/rest_api/types/experiment_score_write.py +20 -0
- opik/rest_api/types/experiment_status.py +5 -0
- opik/rest_api/types/feedback.py +25 -1
- opik/rest_api/types/feedback_create.py +20 -1
- opik/rest_api/types/feedback_object_public.py +27 -1
- opik/rest_api/types/feedback_public.py +25 -1
- opik/rest_api/types/feedback_score_batch_item.py +2 -1
- opik/rest_api/types/feedback_score_batch_item_thread.py +2 -1
- opik/rest_api/types/feedback_score_public.py +4 -0
- opik/rest_api/types/feedback_update.py +20 -1
- opik/rest_api/types/group_content_with_aggregations.py +1 -0
- opik/rest_api/types/group_detail.py +19 -0
- opik/rest_api/types/group_details.py +20 -0
- opik/rest_api/types/guardrail.py +1 -0
- opik/rest_api/types/guardrail_write.py +1 -0
- opik/rest_api/types/ids_holder.py +19 -0
- opik/rest_api/types/image_url.py +20 -0
- opik/rest_api/types/image_url_public.py +20 -0
- opik/rest_api/types/image_url_write.py +20 -0
- opik/rest_api/types/llm_as_judge_message.py +5 -1
- opik/rest_api/types/llm_as_judge_message_content.py +26 -0
- opik/rest_api/types/llm_as_judge_message_content_public.py +26 -0
- opik/rest_api/types/llm_as_judge_message_content_write.py +26 -0
- opik/rest_api/types/llm_as_judge_message_public.py +5 -1
- opik/rest_api/types/llm_as_judge_message_write.py +5 -1
- opik/rest_api/types/llm_as_judge_model_parameters.py +3 -0
- opik/rest_api/types/llm_as_judge_model_parameters_public.py +3 -0
- opik/rest_api/types/llm_as_judge_model_parameters_write.py +3 -0
- opik/rest_api/types/manual_evaluation_request.py +38 -0
- opik/rest_api/types/manual_evaluation_request_entity_type.py +5 -0
- opik/rest_api/types/manual_evaluation_response.py +27 -0
- opik/rest_api/types/optimization.py +4 -2
- opik/rest_api/types/optimization_public.py +4 -2
- opik/rest_api/types/optimization_public_status.py +3 -1
- opik/rest_api/types/optimization_status.py +3 -1
- opik/rest_api/types/optimization_studio_config.py +27 -0
- opik/rest_api/types/optimization_studio_config_public.py +27 -0
- opik/rest_api/types/optimization_studio_config_write.py +27 -0
- opik/rest_api/types/optimization_studio_log.py +22 -0
- opik/rest_api/types/optimization_write.py +4 -2
- opik/rest_api/types/optimization_write_status.py +3 -1
- opik/rest_api/types/project.py +1 -0
- opik/rest_api/types/project_detailed.py +1 -0
- opik/rest_api/types/project_reference.py +31 -0
- opik/rest_api/types/project_reference_public.py +31 -0
- opik/rest_api/types/project_stats_summary_item.py +1 -0
- opik/rest_api/types/prompt.py +6 -0
- opik/rest_api/types/prompt_detail.py +6 -0
- opik/rest_api/types/prompt_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_public.py +6 -0
- opik/rest_api/types/prompt_public_template_structure.py +5 -0
- opik/rest_api/types/prompt_template_structure.py +5 -0
- opik/rest_api/types/prompt_version.py +3 -0
- opik/rest_api/types/prompt_version_detail.py +3 -0
- opik/rest_api/types/prompt_version_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_link.py +1 -0
- opik/rest_api/types/prompt_version_link_public.py +1 -0
- opik/rest_api/types/prompt_version_page_public.py +5 -0
- opik/rest_api/types/prompt_version_public.py +3 -0
- opik/rest_api/types/prompt_version_public_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_update.py +33 -0
- opik/rest_api/types/provider_api_key.py +9 -0
- opik/rest_api/types/provider_api_key_provider.py +1 -1
- opik/rest_api/types/provider_api_key_public.py +9 -0
- opik/rest_api/types/provider_api_key_public_provider.py +1 -1
- opik/rest_api/types/score_name.py +1 -0
- opik/rest_api/types/service_toggles_config.py +18 -0
- opik/rest_api/types/span.py +1 -2
- opik/rest_api/types/span_enrichment_options.py +31 -0
- opik/rest_api/types/span_experiment_item_bulk_write_view.py +1 -2
- opik/rest_api/types/span_filter.py +23 -0
- opik/rest_api/types/span_filter_operator.py +21 -0
- opik/rest_api/types/span_filter_write.py +23 -0
- opik/rest_api/types/span_filter_write_operator.py +21 -0
- opik/rest_api/types/span_llm_as_judge_code.py +27 -0
- opik/rest_api/types/span_llm_as_judge_code_public.py +27 -0
- opik/rest_api/types/span_llm_as_judge_code_write.py +27 -0
- opik/rest_api/types/span_public.py +1 -2
- opik/rest_api/types/span_update.py +46 -0
- opik/rest_api/types/span_user_defined_metric_python_code.py +20 -0
- opik/rest_api/types/span_user_defined_metric_python_code_public.py +20 -0
- opik/rest_api/types/span_user_defined_metric_python_code_write.py +20 -0
- opik/rest_api/types/span_write.py +1 -2
- opik/rest_api/types/studio_evaluation.py +20 -0
- opik/rest_api/types/studio_evaluation_public.py +20 -0
- opik/rest_api/types/studio_evaluation_write.py +20 -0
- opik/rest_api/types/studio_llm_model.py +21 -0
- opik/rest_api/types/studio_llm_model_public.py +21 -0
- opik/rest_api/types/studio_llm_model_write.py +21 -0
- opik/rest_api/types/studio_message.py +20 -0
- opik/rest_api/types/studio_message_public.py +20 -0
- opik/rest_api/types/studio_message_write.py +20 -0
- opik/rest_api/types/studio_metric.py +21 -0
- opik/rest_api/types/studio_metric_public.py +21 -0
- opik/rest_api/types/studio_metric_write.py +21 -0
- opik/rest_api/types/studio_optimizer.py +21 -0
- opik/rest_api/types/studio_optimizer_public.py +21 -0
- opik/rest_api/types/studio_optimizer_write.py +21 -0
- opik/rest_api/types/studio_prompt.py +20 -0
- opik/rest_api/types/studio_prompt_public.py +20 -0
- opik/rest_api/types/studio_prompt_write.py +20 -0
- opik/rest_api/types/trace.py +11 -2
- opik/rest_api/types/trace_enrichment_options.py +32 -0
- opik/rest_api/types/trace_experiment_item_bulk_write_view.py +1 -2
- opik/rest_api/types/trace_filter.py +23 -0
- opik/rest_api/types/trace_filter_operator.py +21 -0
- opik/rest_api/types/trace_filter_write.py +23 -0
- opik/rest_api/types/trace_filter_write_operator.py +21 -0
- opik/rest_api/types/trace_public.py +11 -2
- opik/rest_api/types/trace_thread_filter_write.py +23 -0
- opik/rest_api/types/trace_thread_filter_write_operator.py +21 -0
- opik/rest_api/types/trace_thread_identifier.py +1 -0
- opik/rest_api/types/trace_update.py +39 -0
- opik/rest_api/types/trace_write.py +1 -2
- opik/rest_api/types/value_entry.py +2 -0
- opik/rest_api/types/value_entry_compare.py +2 -0
- opik/rest_api/types/value_entry_experiment_item_bulk_write_view.py +2 -0
- opik/rest_api/types/value_entry_public.py +2 -0
- opik/rest_api/types/video_url.py +19 -0
- opik/rest_api/types/video_url_public.py +19 -0
- opik/rest_api/types/video_url_write.py +19 -0
- opik/rest_api/types/webhook.py +28 -0
- opik/rest_api/types/webhook_examples.py +19 -0
- opik/rest_api/types/webhook_public.py +28 -0
- opik/rest_api/types/webhook_test_result.py +23 -0
- opik/rest_api/types/webhook_test_result_status.py +5 -0
- opik/rest_api/types/webhook_write.py +23 -0
- opik/rest_api/types/welcome_wizard_tracking.py +22 -0
- opik/rest_api/types/workspace_configuration.py +5 -0
- opik/rest_api/welcome_wizard/__init__.py +4 -0
- opik/rest_api/welcome_wizard/client.py +195 -0
- opik/rest_api/welcome_wizard/raw_client.py +208 -0
- opik/rest_api/workspaces/client.py +14 -2
- opik/rest_api/workspaces/raw_client.py +10 -0
- opik/s3_httpx_client.py +14 -1
- opik/simulation/__init__.py +6 -0
- opik/simulation/simulated_user.py +99 -0
- opik/simulation/simulator.py +108 -0
- opik/synchronization.py +5 -6
- opik/{decorator/tracing_runtime_config.py → tracing_runtime_config.py} +6 -7
- opik/types.py +36 -0
- opik/validation/chat_prompt_messages.py +241 -0
- opik/validation/feedback_score.py +3 -3
- opik/validation/validator.py +28 -0
- opik-1.9.71.dist-info/METADATA +370 -0
- opik-1.9.71.dist-info/RECORD +1110 -0
- opik/api_objects/prompt/prompt.py +0 -112
- opik/cli.py +0 -193
- opik/hooks.py +0 -13
- opik/integrations/bedrock/chunks_aggregator.py +0 -55
- opik/integrations/bedrock/helpers.py +0 -8
- opik/rest_api/types/automation_rule_evaluator_object_public.py +0 -100
- opik/rest_api/types/json_node_experiment_item_bulk_write_view.py +0 -5
- opik-1.8.39.dist-info/METADATA +0 -339
- opik-1.8.39.dist-info/RECORD +0 -790
- /opik/{evaluation/metrics/conversation/conversational_coherence → decorator/context_manager}/__init__.py +0 -0
- /opik/evaluation/metrics/conversation/{session_completeness → llm_judges/conversational_coherence}/__init__.py +0 -0
- /opik/evaluation/metrics/conversation/{conversational_coherence → llm_judges/conversational_coherence}/schema.py +0 -0
- /opik/evaluation/metrics/conversation/{user_frustration → llm_judges/session_completeness}/__init__.py +0 -0
- /opik/evaluation/metrics/conversation/{session_completeness → llm_judges/session_completeness}/schema.py +0 -0
- /opik/evaluation/metrics/conversation/{user_frustration → llm_judges/user_frustration}/schema.py +0 -0
- /opik/integrations/bedrock/{stream_wrappers.py → converse/stream_wrappers.py} +0 -0
- /opik/rest_api/{spans/types → types}/span_update_type.py +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/WHEEL +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/entry_points.txt +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/licenses/LICENSE +0 -0
- {opik-1.8.39.dist-info → opik-1.9.71.dist-info}/top_level.txt +0 -0
|
@@ -29,6 +29,7 @@ COLUMNS = {
|
|
|
29
29
|
"type": "string",
|
|
30
30
|
"model": "string",
|
|
31
31
|
"provider": "string",
|
|
32
|
+
"template_structure": "string",
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
SUPPORTED_OPERATORS = {
|
|
@@ -53,7 +54,7 @@ SUPPORTED_OPERATORS = {
|
|
|
53
54
|
],
|
|
54
55
|
"output": ["=", "contains", "not_contains"],
|
|
55
56
|
"metadata": ["=", "contains", ">", "<"],
|
|
56
|
-
"feedback_scores": ["=", ">", "<", ">=", "<="],
|
|
57
|
+
"feedback_scores": ["=", ">", "<", ">=", "<=", "is_empty", "is_not_empty"],
|
|
57
58
|
"tags": ["contains"],
|
|
58
59
|
"usage.total_tokens": ["=", "!=", ">", "<", ">=", "<="],
|
|
59
60
|
"usage.prompt_tokens": ["=", "!=", ">", "<", ">=", "<="],
|
|
@@ -111,8 +112,28 @@ SUPPORTED_OPERATORS = {
|
|
|
111
112
|
">",
|
|
112
113
|
"<",
|
|
113
114
|
],
|
|
115
|
+
"default": [
|
|
116
|
+
"=",
|
|
117
|
+
"contains",
|
|
118
|
+
"not_contains",
|
|
119
|
+
"starts_with",
|
|
120
|
+
"ends_with",
|
|
121
|
+
"!=",
|
|
122
|
+
">",
|
|
123
|
+
"<",
|
|
124
|
+
],
|
|
125
|
+
"template_structure": [
|
|
126
|
+
"=",
|
|
127
|
+
"contains",
|
|
128
|
+
"not_contains",
|
|
129
|
+
"starts_with",
|
|
130
|
+
"ends_with",
|
|
131
|
+
"!=",
|
|
132
|
+
],
|
|
114
133
|
}
|
|
115
134
|
|
|
135
|
+
OPERATORS_WITHOUT_VALUES = {"is_empty", "is_not_empty"}
|
|
136
|
+
|
|
116
137
|
|
|
117
138
|
class OpikQueryLanguage:
|
|
118
139
|
"""
|
|
@@ -252,16 +273,25 @@ class OpikQueryLanguage:
|
|
|
252
273
|
"key": "",
|
|
253
274
|
"type": COLUMNS[f"usage.{key}"],
|
|
254
275
|
}
|
|
255
|
-
|
|
276
|
+
elif field in COLUMNS:
|
|
256
277
|
return {"field": field, "key": key, "type": COLUMNS[field]}
|
|
278
|
+
else:
|
|
279
|
+
# defaults to string
|
|
280
|
+
return {"field": field, "key": key, "type": "string"}
|
|
257
281
|
|
|
258
|
-
|
|
282
|
+
elif field in COLUMNS:
|
|
259
283
|
return {"field": field, "key": "", "type": COLUMNS[field]}
|
|
284
|
+
else:
|
|
285
|
+
# defaults to string
|
|
286
|
+
return {"field": field, "key": "", "type": "string"}
|
|
260
287
|
|
|
261
288
|
def _parse_operator(self, parsed_field: str) -> Dict[str, Any]:
|
|
262
289
|
# Skip whitespace
|
|
263
290
|
self._skip_whitespace()
|
|
264
291
|
|
|
292
|
+
if parsed_field not in SUPPORTED_OPERATORS:
|
|
293
|
+
parsed_field = "default"
|
|
294
|
+
|
|
265
295
|
# Parse the operator
|
|
266
296
|
if self.query_string[self._cursor] == "=":
|
|
267
297
|
operator = "="
|
|
@@ -356,8 +386,12 @@ class OpikQueryLanguage:
|
|
|
356
386
|
# Parse operators
|
|
357
387
|
parsed_operator = self._parse_operator(parsed_field["field"])
|
|
358
388
|
|
|
359
|
-
|
|
360
|
-
|
|
389
|
+
operator_name = parsed_operator.get("operator", "")
|
|
390
|
+
if operator_name in OPERATORS_WITHOUT_VALUES:
|
|
391
|
+
# For operators without values, use empty string as value
|
|
392
|
+
parsed_value = {"value": ""}
|
|
393
|
+
else:
|
|
394
|
+
parsed_value = self._parse_value()
|
|
361
395
|
|
|
362
396
|
expressions.append({**parsed_field, **parsed_operator, **parsed_value})
|
|
363
397
|
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
from .prompt import Prompt
|
|
1
|
+
from .text.prompt import Prompt
|
|
2
|
+
from .text.prompt_template import PromptTemplate
|
|
3
|
+
from .chat.chat_prompt import ChatPrompt
|
|
4
|
+
from .chat.chat_prompt_template import ChatPromptTemplate
|
|
2
5
|
from .types import PromptType
|
|
6
|
+
from .base_prompt import BasePrompt
|
|
7
|
+
from .base_prompt_template import BasePromptTemplate
|
|
3
8
|
|
|
4
9
|
__all__ = [
|
|
5
|
-
"Prompt",
|
|
6
10
|
"PromptType",
|
|
11
|
+
"Prompt",
|
|
12
|
+
"ChatPrompt",
|
|
13
|
+
"PromptTemplate",
|
|
14
|
+
"ChatPromptTemplate",
|
|
15
|
+
"BasePrompt",
|
|
16
|
+
"BasePromptTemplate",
|
|
7
17
|
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for prompts.
|
|
3
|
+
|
|
4
|
+
Defines abstract interface that both string and chat prompt variants must implement.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from . import types as prompt_types
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BasePrompt(ABC):
|
|
14
|
+
"""
|
|
15
|
+
Abstract base class for prompts (string and chat).
|
|
16
|
+
|
|
17
|
+
All prompt implementations must provide common properties and methods
|
|
18
|
+
for interacting with the backend API.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def name(self) -> str:
|
|
24
|
+
"""The name of the prompt."""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def commit(self) -> Optional[str]:
|
|
30
|
+
"""The commit hash of the prompt version."""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def metadata(self) -> Optional[Dict[str, Any]]:
|
|
36
|
+
"""The metadata dictionary associated with the prompt."""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def type(self) -> prompt_types.PromptType:
|
|
42
|
+
"""The prompt type (MUSTACHE or JINJA2)."""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
# Internal API fields for backend synchronization
|
|
46
|
+
__internal_api__prompt_id__: str
|
|
47
|
+
__internal_api__version_id__: str
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def format(self, *args: Any, **kwargs: Any) -> Any:
|
|
51
|
+
"""
|
|
52
|
+
Format the prompt with the provided variables.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Formatted output. Type depends on the implementation:
|
|
56
|
+
- Prompt returns str
|
|
57
|
+
- ChatPrompt returns List[Dict[str, MessageContent]]
|
|
58
|
+
"""
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def __internal_api__to_info_dict__(self) -> Dict[str, Any]:
|
|
63
|
+
"""
|
|
64
|
+
Convert the prompt to an info dictionary for serialization.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Dictionary containing prompt metadata and version information.
|
|
68
|
+
"""
|
|
69
|
+
pass
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for prompt templates.
|
|
3
|
+
|
|
4
|
+
Defines abstract interface that both string and chat template variants must implement.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BasePromptTemplate(ABC):
|
|
12
|
+
"""
|
|
13
|
+
Abstract base class for prompt templates (string and chat).
|
|
14
|
+
|
|
15
|
+
All prompt template implementations must provide a format method
|
|
16
|
+
that takes variables and returns formatted output.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def format(self, *args: Any, **kwargs: Any) -> Any:
|
|
21
|
+
"""
|
|
22
|
+
Format the template with the provided variables.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Formatted output. Type depends on the implementation:
|
|
26
|
+
- PromptTemplate returns str
|
|
27
|
+
- ChatPromptTemplate returns List[Dict[str, MessageContent]]
|
|
28
|
+
"""
|
|
29
|
+
pass
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Empty - all exports handled by parent __init__.py
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import json
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple, Type
|
|
4
|
+
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
from opik.rest_api import types as rest_api_types
|
|
8
|
+
from opik.validation import chat_prompt_messages, validator
|
|
9
|
+
from . import chat_prompt_template
|
|
10
|
+
from .. import client as prompt_client
|
|
11
|
+
from .. import types as prompt_types
|
|
12
|
+
from .. import base_prompt
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ChatPrompt(base_prompt.BasePrompt):
|
|
16
|
+
"""
|
|
17
|
+
ChatPrompt class represents a chat-style prompt with a name, message array template and commit hash.
|
|
18
|
+
Similar to Prompt but uses a list of chat messages instead of a string template.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
_parameter_validators: List[Tuple[str, Type[validator.RaisableValidator]]] = [
|
|
22
|
+
("messages", chat_prompt_messages.ChatPromptMessagesValidator),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
name: str,
|
|
28
|
+
messages: List[Dict[str, prompt_types.MessageContent]],
|
|
29
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
30
|
+
type: prompt_types.PromptType = prompt_types.PromptType.MUSTACHE,
|
|
31
|
+
validate_placeholders: bool = False,
|
|
32
|
+
) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Initializes a new instance of the ChatPrompt class.
|
|
35
|
+
Creates a new chat prompt using the opik client and sets the initial state.
|
|
36
|
+
|
|
37
|
+
Parameters:
|
|
38
|
+
name: The name for the prompt.
|
|
39
|
+
messages: List of message dictionaries with 'role' and 'content' fields.
|
|
40
|
+
metadata: Optional metadata to be included in the prompt.
|
|
41
|
+
type: The template type (MUSTACHE or JINJA2).
|
|
42
|
+
validate_placeholders: Whether to validate template placeholders.
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
PromptTemplateStructureMismatch: If a text prompt with the same name already exists (template structure is immutable).
|
|
46
|
+
ValidationError: If messages structure is invalid.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Validate messages structure
|
|
50
|
+
self._validate_inputs(messages=messages)
|
|
51
|
+
|
|
52
|
+
self._chat_template = chat_prompt_template.ChatPromptTemplate(
|
|
53
|
+
messages=messages,
|
|
54
|
+
template_type=type,
|
|
55
|
+
validate_placeholders=validate_placeholders,
|
|
56
|
+
)
|
|
57
|
+
self._name = name
|
|
58
|
+
self._metadata = metadata
|
|
59
|
+
self._type = type
|
|
60
|
+
self._messages = messages
|
|
61
|
+
self._commit: Optional[str] = None
|
|
62
|
+
self.__internal_api__prompt_id__: str
|
|
63
|
+
self.__internal_api__version_id__: str
|
|
64
|
+
|
|
65
|
+
self._sync_with_backend()
|
|
66
|
+
|
|
67
|
+
def _validate_inputs(self, **kwargs: Any) -> None:
|
|
68
|
+
for parameter, validator_class in self._parameter_validators:
|
|
69
|
+
if parameter in kwargs:
|
|
70
|
+
validator_instance = validator_class(kwargs[parameter])
|
|
71
|
+
validator_instance.validate()
|
|
72
|
+
validator_instance.raise_if_validation_failed()
|
|
73
|
+
|
|
74
|
+
def _sync_with_backend(self) -> None:
|
|
75
|
+
from opik.api_objects import opik_client
|
|
76
|
+
|
|
77
|
+
opik_client_ = opik_client.get_client_cached()
|
|
78
|
+
prompt_client_ = prompt_client.PromptClient(opik_client_.rest_client)
|
|
79
|
+
|
|
80
|
+
# Convert messages array to JSON string for backend storage
|
|
81
|
+
messages_str = json.dumps(self._messages)
|
|
82
|
+
|
|
83
|
+
prompt_version = prompt_client_.create_prompt(
|
|
84
|
+
name=self._name,
|
|
85
|
+
prompt=messages_str,
|
|
86
|
+
metadata=self._metadata,
|
|
87
|
+
type=self._type,
|
|
88
|
+
template_structure="chat",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
self._commit = prompt_version.commit
|
|
92
|
+
self.__internal_api__prompt_id__ = prompt_version.prompt_id
|
|
93
|
+
self.__internal_api__version_id__ = prompt_version.id
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
@override
|
|
97
|
+
def name(self) -> str:
|
|
98
|
+
"""The name of the prompt."""
|
|
99
|
+
return self._name
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def template(self) -> List[Dict[str, prompt_types.MessageContent]]:
|
|
103
|
+
"""The chat messages template."""
|
|
104
|
+
return copy.deepcopy(self._messages)
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
@override
|
|
108
|
+
def commit(self) -> Optional[str]:
|
|
109
|
+
"""The commit hash of the prompt."""
|
|
110
|
+
return self._commit
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
@override
|
|
114
|
+
def metadata(self) -> Optional[Dict[str, Any]]:
|
|
115
|
+
"""The metadata dictionary associated with the prompt"""
|
|
116
|
+
return copy.deepcopy(self._metadata)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
@override
|
|
120
|
+
def type(self) -> prompt_types.PromptType:
|
|
121
|
+
"""The prompt type of the prompt."""
|
|
122
|
+
return self._type
|
|
123
|
+
|
|
124
|
+
@override
|
|
125
|
+
def format(
|
|
126
|
+
self,
|
|
127
|
+
variables: Dict[str, Any],
|
|
128
|
+
supported_modalities: Optional[prompt_types.SupportedModalities] = None,
|
|
129
|
+
) -> List[Dict[str, prompt_types.MessageContent]]:
|
|
130
|
+
"""
|
|
131
|
+
Renders the chat template with provided variables.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
variables: Dictionary of variables to substitute in the template.
|
|
135
|
+
supported_modalities: Optional dictionary specifying which modalities are supported
|
|
136
|
+
by the target model. Keys are modality names ("vision" or "video") and values
|
|
137
|
+
are booleans indicating support. When a modality is not supported (False or not
|
|
138
|
+
specified), structured content parts (e.g., images, videos) are replaced with
|
|
139
|
+
text placeholders like "<<<image>>>" or "<<<video>>>". When supported (True),
|
|
140
|
+
the structured content is preserved as-is.
|
|
141
|
+
Example: {"vision": True, "video": False}
|
|
142
|
+
|
|
143
|
+
If not specified, all modalities default to SUPPORTED. Example: {"vision": True, "video": False}
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
A list of rendered message dictionaries with variables substituted and multimodal
|
|
147
|
+
content either preserved or replaced with placeholders based on supported_modalities.
|
|
148
|
+
"""
|
|
149
|
+
if supported_modalities is None:
|
|
150
|
+
supported_modalities = {
|
|
151
|
+
"vision": True,
|
|
152
|
+
"video": True,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return self._chat_template.format(
|
|
156
|
+
variables=variables, supported_modalities=supported_modalities
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
@override
|
|
160
|
+
def __internal_api__to_info_dict__(self) -> Dict[str, Any]:
|
|
161
|
+
"""
|
|
162
|
+
Convert the prompt to an info dictionary for serialization.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Dictionary containing prompt metadata and version information.
|
|
166
|
+
"""
|
|
167
|
+
info_dict: Dict[str, Any] = {
|
|
168
|
+
"name": self.name,
|
|
169
|
+
"version": {
|
|
170
|
+
"template": self.template,
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if self.__internal_api__prompt_id__ is not None:
|
|
175
|
+
info_dict["id"] = self.__internal_api__prompt_id__
|
|
176
|
+
|
|
177
|
+
if self.commit is not None:
|
|
178
|
+
info_dict["version"]["commit"] = self.commit
|
|
179
|
+
|
|
180
|
+
if self.__internal_api__version_id__ is not None:
|
|
181
|
+
info_dict["version"]["id"] = self.__internal_api__version_id__
|
|
182
|
+
|
|
183
|
+
return info_dict
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def from_fern_prompt_version(
|
|
187
|
+
cls,
|
|
188
|
+
name: str,
|
|
189
|
+
prompt_version: rest_api_types.PromptVersionDetail,
|
|
190
|
+
) -> "ChatPrompt":
|
|
191
|
+
# will not call __init__ to avoid API calls, create new instance with __new__
|
|
192
|
+
chat_prompt = cls.__new__(cls)
|
|
193
|
+
|
|
194
|
+
chat_prompt.__internal_api__version_id__ = prompt_version.id
|
|
195
|
+
chat_prompt.__internal_api__prompt_id__ = prompt_version.prompt_id
|
|
196
|
+
|
|
197
|
+
chat_prompt._name = name
|
|
198
|
+
|
|
199
|
+
# Parse messages from JSON string
|
|
200
|
+
messages = json.loads(prompt_version.template)
|
|
201
|
+
chat_prompt._messages = messages
|
|
202
|
+
chat_prompt._chat_template = chat_prompt_template.ChatPromptTemplate(
|
|
203
|
+
messages=messages,
|
|
204
|
+
template_type=prompt_types.PromptType(prompt_version.type)
|
|
205
|
+
or prompt_types.PromptType.MUSTACHE,
|
|
206
|
+
)
|
|
207
|
+
chat_prompt._commit = prompt_version.commit
|
|
208
|
+
chat_prompt._metadata = prompt_version.metadata
|
|
209
|
+
chat_prompt._type = prompt_version.type
|
|
210
|
+
return chat_prompt
|