opik 1.9.5__py3-none-any.whl → 1.9.39__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 +10 -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/dataset/rest_operations.py +5 -0
- opik/api_objects/experiment/experiment.py +46 -49
- opik/api_objects/experiment/helpers.py +34 -10
- opik/api_objects/local_recording.py +8 -3
- opik/api_objects/opik_client.py +230 -48
- opik/api_objects/opik_query_language.py +9 -0
- opik/api_objects/prompt/__init__.py +11 -3
- 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 +193 -0
- opik/api_objects/prompt/chat/chat_prompt_template.py +350 -0
- opik/api_objects/prompt/{chat_content_renderer_registry.py → chat/content_renderer_registry.py} +37 -35
- opik/api_objects/prompt/client.py +101 -30
- 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 +1 -1
- opik/cli/export.py +6 -2
- opik/cli/usage_report/charts.py +39 -10
- opik/cli/usage_report/cli.py +164 -45
- opik/cli/usage_report/pdf.py +14 -1
- opik/config.py +0 -5
- opik/decorator/base_track_decorator.py +37 -40
- opik/decorator/context_manager/span_context_manager.py +9 -0
- opik/decorator/context_manager/trace_context_manager.py +5 -0
- opik/dict_utils.py +3 -3
- opik/evaluation/__init__.py +13 -2
- opik/evaluation/engine/engine.py +195 -223
- opik/evaluation/engine/helpers.py +8 -7
- opik/evaluation/engine/metrics_evaluator.py +237 -0
- opik/evaluation/evaluation_result.py +35 -1
- opik/evaluation/evaluator.py +318 -30
- opik/evaluation/models/litellm/util.py +78 -6
- opik/evaluation/models/model_capabilities.py +33 -0
- opik/evaluation/report.py +14 -2
- opik/evaluation/rest_operations.py +36 -33
- opik/evaluation/test_case.py +2 -2
- opik/evaluation/types.py +9 -1
- opik/exceptions.py +17 -0
- opik/hooks/__init__.py +17 -1
- opik/hooks/anonymizer_hook.py +36 -0
- opik/id_helpers.py +18 -0
- opik/integrations/adk/helpers.py +16 -7
- opik/integrations/adk/legacy_opik_tracer.py +7 -4
- opik/integrations/adk/opik_tracer.py +3 -1
- opik/integrations/adk/patchers/adk_otel_tracer/opik_adk_otel_tracer.py +7 -3
- opik/integrations/adk/recursive_callback_injector.py +1 -6
- opik/integrations/dspy/callback.py +1 -4
- opik/integrations/haystack/opik_connector.py +2 -2
- opik/integrations/haystack/opik_tracer.py +2 -4
- opik/integrations/langchain/opik_tracer.py +273 -82
- opik/integrations/llama_index/callback.py +110 -108
- opik/integrations/openai/agents/opik_tracing_processor.py +1 -2
- opik/integrations/openai/opik_tracker.py +1 -1
- opik/message_processing/batching/batchers.py +11 -7
- opik/message_processing/encoder_helpers.py +79 -0
- opik/message_processing/messages.py +25 -1
- opik/message_processing/online_message_processor.py +23 -8
- opik/opik_context.py +7 -7
- opik/rest_api/__init__.py +188 -12
- opik/rest_api/client.py +3 -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 +893 -89
- opik/rest_api/datasets/raw_client.py +1328 -87
- opik/rest_api/experiments/client.py +30 -2
- opik/rest_api/experiments/raw_client.py +26 -0
- opik/rest_api/feedback_definitions/types/find_feedback_definitions_request_type.py +1 -1
- opik/rest_api/optimizations/client.py +302 -0
- opik/rest_api/optimizations/raw_client.py +463 -0
- 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 +34 -4
- opik/rest_api/prompts/raw_client.py +32 -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 +148 -64
- opik/rest_api/spans/raw_client.py +210 -83
- opik/rest_api/spans/types/__init__.py +0 -2
- opik/rest_api/traces/client.py +241 -73
- opik/rest_api/traces/raw_client.py +344 -90
- opik/rest_api/types/__init__.py +200 -15
- opik/rest_api/types/aggregation_data.py +1 -0
- opik/rest_api/types/alert_trigger_config_public_type.py +6 -1
- opik/rest_api/types/alert_trigger_config_type.py +6 -1
- opik/rest_api/types/alert_trigger_config_write_type.py +6 -1
- opik/rest_api/types/automation_rule_evaluator.py +23 -1
- 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_public.py → automation_rule_evaluator_object_object_public.py} +32 -10
- opik/rest_api/types/automation_rule_evaluator_page_public.py +2 -2
- opik/rest_api/types/automation_rule_evaluator_public.py +23 -1
- 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_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 +23 -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_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 +23 -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 +2 -0
- opik/rest_api/types/dataset_item.py +2 -0
- opik/rest_api/types/dataset_item_compare.py +2 -0
- opik/rest_api/types/dataset_item_filter.py +23 -0
- opik/rest_api/types/dataset_item_filter_operator.py +21 -0
- opik/rest_api/types/dataset_item_page_compare.py +1 -0
- opik/rest_api/types/dataset_item_page_public.py +1 -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 +2 -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 +49 -0
- opik/rest_api/types/experiment.py +2 -0
- opik/rest_api/types/experiment_public.py +2 -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/feedback.py +20 -1
- opik/rest_api/types/feedback_create.py +16 -1
- opik/rest_api/types/feedback_object_public.py +22 -1
- opik/rest_api/types/feedback_public.py +20 -1
- opik/rest_api/types/feedback_score_public.py +4 -0
- opik/rest_api/types/feedback_update.py +16 -1
- 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 +24 -0
- opik/rest_api/types/llm_as_judge_message_content_public.py +24 -0
- opik/rest_api/types/llm_as_judge_message_content_write.py +24 -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 +2 -0
- opik/rest_api/types/llm_as_judge_model_parameters_public.py +2 -0
- opik/rest_api/types/llm_as_judge_model_parameters_write.py +2 -0
- opik/rest_api/types/optimization.py +2 -0
- opik/rest_api/types/optimization_public.py +2 -0
- 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 +2 -0
- opik/rest_api/types/optimization_write_status.py +3 -1
- 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 +2 -0
- opik/rest_api/types/prompt_version_detail.py +2 -0
- opik/rest_api/types/prompt_version_detail_template_structure.py +5 -0
- opik/rest_api/types/prompt_version_public.py +2 -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/score_name.py +1 -0
- opik/rest_api/types/service_toggles_config.py +6 -0
- opik/rest_api/types/span_enrichment_options.py +31 -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_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_update.py +46 -0
- 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 +6 -0
- opik/rest_api/types/trace_public.py +6 -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_update.py +19 -0
- opik/rest_api/types/trace_update.py +39 -0
- 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/synchronization.py +5 -6
- opik/{decorator/tracing_runtime_config.py → tracing_runtime_config.py} +6 -7
- {opik-1.9.5.dist-info → opik-1.9.39.dist-info}/METADATA +5 -4
- {opik-1.9.5.dist-info → opik-1.9.39.dist-info}/RECORD +246 -151
- opik/api_objects/prompt/chat_prompt_template.py +0 -164
- opik/api_objects/prompt/prompt.py +0 -131
- /opik/rest_api/{spans/types → types}/span_update_type.py +0 -0
- {opik-1.9.5.dist-info → opik-1.9.39.dist-info}/WHEEL +0 -0
- {opik-1.9.5.dist-info → opik-1.9.39.dist-info}/entry_points.txt +0 -0
- {opik-1.9.5.dist-info → opik-1.9.39.dist-info}/licenses/LICENSE +0 -0
- {opik-1.9.5.dist-info → opik-1.9.39.dist-info}/top_level.txt +0 -0
|
@@ -1,21 +1,26 @@
|
|
|
1
|
+
import contextvars
|
|
1
2
|
import logging
|
|
2
|
-
from typing import Optional, Dict, List,
|
|
3
|
+
from typing import Optional, Dict, Any, List, Union
|
|
3
4
|
import uuid
|
|
4
5
|
|
|
5
6
|
from llama_index.core.callbacks import schema as llama_index_schema
|
|
6
7
|
from llama_index.core.callbacks import base_handler
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
from opik import context_storage, tracing_runtime_config
|
|
10
|
+
from opik.decorator import arguments_helpers, span_creation_handler
|
|
10
11
|
from opik.api_objects import opik_client, span, trace
|
|
11
12
|
|
|
12
13
|
from . import event_parsing_utils
|
|
13
|
-
from ...api_objects import helpers
|
|
14
14
|
|
|
15
15
|
LOGGER = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
|
-
|
|
18
17
|
INDEX_CONSTRUCTION_TRACE_NAME = "index_construction"
|
|
18
|
+
LLAMA_INDEX_METADATA = {"created_from": "llama_index"}
|
|
19
|
+
|
|
20
|
+
# Context variable for root trace/span created by LlamaIndex
|
|
21
|
+
_llama_root: contextvars.ContextVar[Optional[Union[span.SpanData, trace.TraceData]]] = (
|
|
22
|
+
contextvars.ContextVar("_llama_root", default=None)
|
|
23
|
+
)
|
|
19
24
|
|
|
20
25
|
|
|
21
26
|
def _get_last_event(trace_map: Dict[str, List[str]]) -> str:
|
|
@@ -36,20 +41,13 @@ class LlamaIndexCallbackHandler(base_handler.BaseCallbackHandler):
|
|
|
36
41
|
project_name: Optional[str] = None,
|
|
37
42
|
skip_index_construction_trace: bool = False,
|
|
38
43
|
):
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
processing.
|
|
47
|
-
event_ends_to_ignore: Optional list of event end types to be ignored during
|
|
48
|
-
processing.
|
|
49
|
-
project_name: Optional string representing the project name to establish context in
|
|
50
|
-
client operations.
|
|
51
|
-
skip_index_construction_trace: A boolean value determining whether to skip creation of trace/spans of index
|
|
52
|
-
construction.
|
|
44
|
+
"""Initialize LlamaIndex callback handler for Opik tracing.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
event_starts_to_ignore: Event start types to be ignored during processing.
|
|
48
|
+
event_ends_to_ignore: Event end types to be ignored during processing.
|
|
49
|
+
project_name: Project name for trace/span context.
|
|
50
|
+
skip_index_construction_trace: Whether to skip index construction traces.
|
|
53
51
|
"""
|
|
54
52
|
event_starts_to_ignore = (
|
|
55
53
|
event_starts_to_ignore if event_starts_to_ignore else []
|
|
@@ -62,31 +60,13 @@ class LlamaIndexCallbackHandler(base_handler.BaseCallbackHandler):
|
|
|
62
60
|
|
|
63
61
|
self._skip_index_construction_trace = skip_index_construction_trace
|
|
64
62
|
self._project_name = project_name
|
|
65
|
-
self._opik_client = opik_client.
|
|
66
|
-
|
|
67
|
-
project_name=project_name,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
self._opik_trace_data: Optional[trace.TraceData] = None
|
|
63
|
+
self._opik_client = opik_client.get_client_cached()
|
|
64
|
+
self._opik_context_storage = context_storage.get_current_context_instance()
|
|
71
65
|
|
|
66
|
+
# Event tracking - shared across contexts, but events have unique IDs
|
|
72
67
|
self._map_event_id_to_span_data: Dict[str, span.SpanData] = {}
|
|
73
68
|
self._map_event_id_to_output: Dict[str, Any] = {}
|
|
74
69
|
|
|
75
|
-
def _create_trace_data(self, trace_name: Optional[str]) -> trace.TraceData:
|
|
76
|
-
trace_data = trace.TraceData(
|
|
77
|
-
name=trace_name,
|
|
78
|
-
metadata={"created_from": "llama_index"},
|
|
79
|
-
project_name=self._project_name,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
self._opik_client.config.log_start_trace_span
|
|
84
|
-
and tracing_runtime_config.is_tracing_active()
|
|
85
|
-
):
|
|
86
|
-
self._opik_client.trace(**trace_data.as_start_parameters)
|
|
87
|
-
|
|
88
|
-
return trace_data
|
|
89
|
-
|
|
90
70
|
def start_trace(self, trace_id: Optional[str] = None) -> None:
|
|
91
71
|
if (
|
|
92
72
|
self._skip_index_construction_trace
|
|
@@ -94,18 +74,29 @@ class LlamaIndexCallbackHandler(base_handler.BaseCallbackHandler):
|
|
|
94
74
|
):
|
|
95
75
|
return
|
|
96
76
|
|
|
97
|
-
|
|
98
|
-
existing_trace_data = opik_context.get_current_trace_data()
|
|
99
|
-
if existing_trace_data is not None:
|
|
100
|
-
self._opik_trace_data = existing_trace_data
|
|
101
|
-
else:
|
|
102
|
-
self._opik_trace_data = self._create_trace_data(trace_name=trace_id)
|
|
77
|
+
trace_name = trace_id if trace_id else "llama_index_operation"
|
|
103
78
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
79
|
+
span_creation_result = span_creation_handler.create_span_respecting_context(
|
|
80
|
+
start_span_arguments=arguments_helpers.StartSpanParameters(
|
|
81
|
+
name=trace_name,
|
|
82
|
+
type="general",
|
|
83
|
+
project_name=self._project_name,
|
|
84
|
+
metadata=LLAMA_INDEX_METADATA,
|
|
85
|
+
),
|
|
86
|
+
distributed_trace_headers=None,
|
|
87
|
+
opik_context_storage=self._opik_context_storage,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if span_creation_result.trace_data is not None:
|
|
91
|
+
self._opik_context_storage.set_trace_data(span_creation_result.trace_data)
|
|
92
|
+
self._opik_client.trace(
|
|
93
|
+
**span_creation_result.trace_data.as_start_parameters
|
|
94
|
+
)
|
|
95
|
+
_llama_root.set(span_creation_result.trace_data)
|
|
96
|
+
else:
|
|
97
|
+
self._opik_context_storage.add_span_data(span_creation_result.span_data)
|
|
98
|
+
self._opik_client.span(**span_creation_result.span_data.as_start_parameters)
|
|
99
|
+
_llama_root.set(span_creation_result.span_data)
|
|
109
100
|
|
|
110
101
|
def end_trace(
|
|
111
102
|
self,
|
|
@@ -115,21 +106,26 @@ class LlamaIndexCallbackHandler(base_handler.BaseCallbackHandler):
|
|
|
115
106
|
if not trace_map:
|
|
116
107
|
return
|
|
117
108
|
|
|
118
|
-
|
|
109
|
+
root = _llama_root.get()
|
|
110
|
+
if root is None:
|
|
111
|
+
return
|
|
112
|
+
|
|
119
113
|
last_event = _get_last_event(trace_map)
|
|
120
114
|
last_event_output = self._map_event_id_to_output.get(last_event, None)
|
|
121
115
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
self.
|
|
116
|
+
root.init_end_time().update(output=last_event_output)
|
|
117
|
+
|
|
118
|
+
if isinstance(root, span.SpanData):
|
|
119
|
+
# We created a wrapper span (external trace existed)
|
|
120
|
+
self._opik_client.span(**root.as_parameters)
|
|
121
|
+
self._opik_context_storage.pop_span_data(ensure_id=root.id)
|
|
122
|
+
elif isinstance(root, trace.TraceData):
|
|
123
|
+
# We created a trace (no external trace existed)
|
|
124
|
+
self._opik_client.trace(**root.as_parameters)
|
|
125
|
+
self._opik_context_storage.pop_trace_data(ensure_id=root.id)
|
|
128
126
|
|
|
129
|
-
#
|
|
130
|
-
|
|
131
|
-
# individually cleaned after each event is ended
|
|
132
|
-
self._map_event_id_to_output.clear()
|
|
127
|
+
# Clean up
|
|
128
|
+
_llama_root.set(None)
|
|
133
129
|
|
|
134
130
|
def on_event_start(
|
|
135
131
|
self,
|
|
@@ -142,53 +138,60 @@ class LlamaIndexCallbackHandler(base_handler.BaseCallbackHandler):
|
|
|
142
138
|
if not event_id:
|
|
143
139
|
event_id = str(uuid.uuid4())
|
|
144
140
|
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
root_span_or_trace = _llama_root.get()
|
|
142
|
+
|
|
143
|
+
if root_span_or_trace is None:
|
|
147
144
|
if not self._skip_index_construction_trace:
|
|
148
145
|
LOGGER.warning(
|
|
149
|
-
"No trace
|
|
150
|
-
"
|
|
151
|
-
|
|
146
|
+
"No active LlamaIndex trace/span found in context. "
|
|
147
|
+
"parent_id=%s, event_type=%s, event_id=%s",
|
|
148
|
+
parent_id,
|
|
149
|
+
event_type,
|
|
150
|
+
event_id,
|
|
152
151
|
)
|
|
153
|
-
|
|
154
152
|
return event_id
|
|
155
153
|
|
|
156
|
-
# Get parent span Id if it exists
|
|
157
|
-
if parent_id and parent_id in self._map_event_id_to_span_data:
|
|
158
|
-
opik_parent_id = self._map_event_id_to_span_data[parent_id].id
|
|
159
|
-
else:
|
|
160
|
-
opik_parent_id = None
|
|
161
|
-
|
|
162
|
-
# Compute the span input based on the event payload
|
|
163
154
|
span_input = event_parsing_utils.get_span_input_from_events(event_type, payload)
|
|
164
155
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
156
|
+
# Skip creating span if event duplicates root operation name
|
|
157
|
+
root_name = root_span_or_trace.name if root_span_or_trace else None
|
|
158
|
+
event_duplicates_root = (
|
|
159
|
+
parent_id == llama_index_schema.BASE_TRACE_EVENT
|
|
160
|
+
and event_type.value == root_name
|
|
169
161
|
)
|
|
162
|
+
if event_duplicates_root:
|
|
163
|
+
if span_input:
|
|
164
|
+
root_span_or_trace.update(input=span_input)
|
|
165
|
+
return event_id
|
|
170
166
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
167
|
+
span_creation_result = span_creation_handler.create_span_respecting_context(
|
|
168
|
+
start_span_arguments=arguments_helpers.StartSpanParameters(
|
|
169
|
+
name=event_type.value,
|
|
170
|
+
input=span_input,
|
|
171
|
+
type=(
|
|
172
|
+
"llm"
|
|
173
|
+
if event_type == llama_index_schema.CBEventType.LLM
|
|
174
|
+
else "general"
|
|
175
|
+
),
|
|
176
|
+
project_name=self._project_name,
|
|
177
|
+
metadata=LLAMA_INDEX_METADATA,
|
|
178
178
|
),
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
distributed_trace_headers=None,
|
|
180
|
+
opik_context_storage=self._opik_context_storage,
|
|
181
181
|
)
|
|
182
|
+
span_data = span_creation_result.span_data
|
|
182
183
|
self._map_event_id_to_span_data[event_id] = span_data
|
|
184
|
+
self._opik_context_storage.add_span_data(span_data)
|
|
185
|
+
|
|
183
186
|
if (
|
|
184
187
|
self._opik_client.config.log_start_trace_span
|
|
185
188
|
and tracing_runtime_config.is_tracing_active()
|
|
186
189
|
):
|
|
187
190
|
self._opik_client.span(**span_data.as_start_parameters)
|
|
188
191
|
|
|
189
|
-
#
|
|
190
|
-
if parent_id == llama_index_schema.BASE_TRACE_EVENT and span_input:
|
|
191
|
-
|
|
192
|
+
# Update root input from first child event
|
|
193
|
+
if parent_id == llama_index_schema.BASE_TRACE_EVENT and span_input is not None:
|
|
194
|
+
root_span_or_trace.update(input=span_input)
|
|
192
195
|
|
|
193
196
|
return event_id
|
|
194
197
|
|
|
@@ -199,32 +202,31 @@ class LlamaIndexCallbackHandler(base_handler.BaseCallbackHandler):
|
|
|
199
202
|
event_id: Optional[str] = None,
|
|
200
203
|
**kwargs: Any,
|
|
201
204
|
) -> None:
|
|
202
|
-
# Get the span output from the event and store it so we can use it if needed
|
|
203
|
-
# when finishing the trace
|
|
204
205
|
span_output = event_parsing_utils.get_span_output_from_event(
|
|
205
206
|
event_type, payload
|
|
206
207
|
)
|
|
207
|
-
|
|
208
208
|
error_info = event_parsing_utils.get_span_error_info(payload)
|
|
209
209
|
|
|
210
|
-
if event_id:
|
|
211
|
-
|
|
210
|
+
if not event_id:
|
|
211
|
+
return
|
|
212
212
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
span_data = self._map_event_id_to_span_data[event_id]
|
|
213
|
+
# Store output for end_trace
|
|
214
|
+
self._map_event_id_to_output[event_id] = span_output
|
|
216
215
|
|
|
217
|
-
|
|
218
|
-
|
|
216
|
+
# Finalize span if it exists
|
|
217
|
+
if event_id in self._map_event_id_to_span_data:
|
|
218
|
+
span_data = self._map_event_id_to_span_data[event_id]
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
220
|
+
llm_usage_info = event_parsing_utils.get_usage_data(payload)
|
|
221
|
+
span_data.update(**llm_usage_info.__dict__)
|
|
222
|
+
span_data.update(output=span_output, error_info=error_info).init_end_time()
|
|
223
|
+
|
|
224
|
+
if tracing_runtime_config.is_tracing_active():
|
|
225
|
+
self._opik_client.span(**span_data.as_parameters)
|
|
225
226
|
|
|
226
|
-
|
|
227
|
+
self._opik_context_storage.pop_span_data(ensure_id=span_data.id)
|
|
228
|
+
del self._map_event_id_to_span_data[event_id]
|
|
227
229
|
|
|
228
230
|
def flush(self) -> None:
|
|
229
|
-
"""
|
|
231
|
+
"""Flush pending Opik data to backend."""
|
|
230
232
|
self._opik_client.flush()
|
|
@@ -3,12 +3,11 @@ from agents import tracing
|
|
|
3
3
|
|
|
4
4
|
import logging
|
|
5
5
|
|
|
6
|
+
from opik import context_storage, tracing_runtime_config
|
|
6
7
|
from opik.api_objects.span import span_data
|
|
7
8
|
from opik.api_objects.trace import trace_data
|
|
8
9
|
from opik.api_objects import opik_client
|
|
9
10
|
from opik.decorator import span_creation_handler, arguments_helpers
|
|
10
|
-
import opik.decorator.tracing_runtime_config as tracing_runtime_config
|
|
11
|
-
import opik.context_storage as context_storage
|
|
12
11
|
|
|
13
12
|
from . import span_data_parsers
|
|
14
13
|
|
|
@@ -18,7 +18,7 @@ def track_openai(
|
|
|
18
18
|
"""Adds Opik tracking wrappers to an OpenAI client.
|
|
19
19
|
|
|
20
20
|
The client is always patched; however every wrapped call checks
|
|
21
|
-
`opik.
|
|
21
|
+
`opik.is_tracing_active()` before emitting
|
|
22
22
|
any telemetry. If tracing is disabled at call time, the wrapped function
|
|
23
23
|
executes normally but no span/trace is sent.
|
|
24
24
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
from typing import Union, cast, List
|
|
2
2
|
|
|
3
|
-
from . import base_batcher, sequence_splitter
|
|
4
|
-
from .. import messages
|
|
5
3
|
from opik.rest_api.types import span_write, trace_write
|
|
6
|
-
import opik.jsonable_encoder as jsonable_encoder
|
|
7
4
|
import opik.dict_utils as dict_utils
|
|
8
5
|
|
|
6
|
+
from . import base_batcher, sequence_splitter
|
|
7
|
+
from .. import messages, encoder_helpers
|
|
8
|
+
|
|
9
9
|
|
|
10
10
|
class CreateSpanMessageBatcher(base_batcher.BaseBatcher):
|
|
11
11
|
def _create_batches_from_accumulated_messages( # type: ignore
|
|
@@ -18,8 +18,10 @@ class CreateSpanMessageBatcher(base_batcher.BaseBatcher):
|
|
|
18
18
|
cleaned_span_write_kwargs = dict_utils.remove_none_from_dict(
|
|
19
19
|
span_write_kwargs
|
|
20
20
|
)
|
|
21
|
-
cleaned_span_write_kwargs =
|
|
22
|
-
cleaned_span_write_kwargs
|
|
21
|
+
cleaned_span_write_kwargs = encoder_helpers.encode_and_anonymize(
|
|
22
|
+
cleaned_span_write_kwargs,
|
|
23
|
+
fields_to_anonymize=messages.CreateSpansBatchMessage.fields_to_anonymize(),
|
|
24
|
+
object_type="span",
|
|
23
25
|
)
|
|
24
26
|
rest_spans.append(span_write.SpanWrite(**cleaned_span_write_kwargs))
|
|
25
27
|
|
|
@@ -52,8 +54,10 @@ class CreateTraceMessageBatcher(base_batcher.BaseBatcher):
|
|
|
52
54
|
cleaned_trace_write_kwargs = dict_utils.remove_none_from_dict(
|
|
53
55
|
trace_write_kwargs
|
|
54
56
|
)
|
|
55
|
-
cleaned_trace_write_kwargs =
|
|
56
|
-
cleaned_trace_write_kwargs
|
|
57
|
+
cleaned_trace_write_kwargs = encoder_helpers.encode_and_anonymize(
|
|
58
|
+
cleaned_trace_write_kwargs,
|
|
59
|
+
fields_to_anonymize=messages.CreateTraceBatchMessage.fields_to_anonymize(),
|
|
60
|
+
object_type="trace",
|
|
57
61
|
)
|
|
58
62
|
rest_traces.append(trace_write.TraceWrite(**cleaned_trace_write_kwargs))
|
|
59
63
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from typing import Dict, Any, Set, List, Literal
|
|
2
|
+
|
|
3
|
+
import opik.hooks
|
|
4
|
+
|
|
5
|
+
from .. import jsonable_encoder
|
|
6
|
+
from ..anonymizer import anonymizer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def encode_and_anonymize(
|
|
10
|
+
kwargs_dict: Dict[str, Any],
|
|
11
|
+
fields_to_anonymize: Set[str],
|
|
12
|
+
object_type: Literal["span", "trace"],
|
|
13
|
+
) -> Dict[str, Any]:
|
|
14
|
+
"""
|
|
15
|
+
Encodes and anonymizes the data in the given dictionary based on the specified
|
|
16
|
+
fields using registered anonymizers. If no anonymizers are registered, the
|
|
17
|
+
function simply encodes the dictionary without anonymization.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
kwargs_dict: The dictionary containing the data to encode
|
|
21
|
+
and anonymize.
|
|
22
|
+
fields_to_anonymize: The set of fields within the dictionary to
|
|
23
|
+
anonymize.
|
|
24
|
+
object_type: A string indicating the type of object ('span' or 'trace')
|
|
25
|
+
that was used to create the kwargs_dict. This is passed to anonymizers
|
|
26
|
+
to provide context about the source object.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
A dictionary that has been encoded and, if applicable, anonymized.
|
|
30
|
+
"""
|
|
31
|
+
# check if any anonymizer was registered
|
|
32
|
+
encoded_obj = jsonable_encoder.encode(kwargs_dict)
|
|
33
|
+
if not opik.hooks.has_anonymizers():
|
|
34
|
+
return encoded_obj
|
|
35
|
+
|
|
36
|
+
anonymizers = opik.hooks.get_anonymizers()
|
|
37
|
+
return anonymize_encoded_obj(
|
|
38
|
+
obj=encoded_obj,
|
|
39
|
+
fields_to_anonymize=fields_to_anonymize,
|
|
40
|
+
anonymizers=anonymizers,
|
|
41
|
+
object_type=object_type,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def anonymize_encoded_obj(
|
|
46
|
+
obj: Dict[str, Any],
|
|
47
|
+
fields_to_anonymize: Set[str],
|
|
48
|
+
anonymizers: List[anonymizer.Anonymizer],
|
|
49
|
+
object_type: Literal["span", "trace"],
|
|
50
|
+
) -> Dict[str, Any]:
|
|
51
|
+
"""
|
|
52
|
+
Anonymizes specified fields in an encoded dictionary using the provided anonymizers.
|
|
53
|
+
This function iterates over the given set of field names and applies each anonymizer
|
|
54
|
+
to the corresponding field in the dictionary, if present. The anonymizers are expected
|
|
55
|
+
to implement an `anonymize` method that takes the field value, field name, and object type
|
|
56
|
+
as arguments. Only fields present in the dictionary and listed in `fields_to_anonymize`
|
|
57
|
+
are anonymized.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
obj: The encoded dictionary whose fields are to be anonymized.
|
|
61
|
+
fields_to_anonymize: A set of field names within the dictionary to anonymize.
|
|
62
|
+
anonymizers: A list of anonymizer instances to apply to each field.
|
|
63
|
+
object_type: A string indicating the type of object ('span' or 'trace'),
|
|
64
|
+
providing context for anonymization.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
The dictionary with specified fields anonymized using the provided anonymizers.
|
|
68
|
+
"""
|
|
69
|
+
if isinstance(obj, dict):
|
|
70
|
+
for field_name in fields_to_anonymize:
|
|
71
|
+
if field_name in obj:
|
|
72
|
+
for anonymizer_instance in anonymizers:
|
|
73
|
+
obj[field_name] = anonymizer_instance.anonymize(
|
|
74
|
+
obj[field_name],
|
|
75
|
+
field_name=field_name,
|
|
76
|
+
object_type=object_type,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return obj
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import datetime
|
|
3
3
|
from dataclasses import field
|
|
4
|
-
from typing import Optional, Any, Dict, List, Union, Literal
|
|
4
|
+
from typing import Optional, Any, Dict, List, Union, Literal, Set
|
|
5
5
|
|
|
6
6
|
from . import arguments_utils
|
|
7
7
|
from ..rest_api.types import span_write, trace_write
|
|
@@ -50,6 +50,10 @@ class CreateTraceMessage(BaseMessage):
|
|
|
50
50
|
data["id"] = data.pop("trace_id")
|
|
51
51
|
return data
|
|
52
52
|
|
|
53
|
+
@staticmethod
|
|
54
|
+
def fields_to_anonymize() -> Set[str]:
|
|
55
|
+
return {"input", "output", "metadata"}
|
|
56
|
+
|
|
53
57
|
|
|
54
58
|
@dataclasses.dataclass
|
|
55
59
|
class UpdateTraceMessage(BaseMessage):
|
|
@@ -78,6 +82,10 @@ class UpdateTraceMessage(BaseMessage):
|
|
|
78
82
|
data["id"] = data.pop("trace_id")
|
|
79
83
|
return data
|
|
80
84
|
|
|
85
|
+
@staticmethod
|
|
86
|
+
def fields_to_anonymize() -> Set[str]:
|
|
87
|
+
return {"input", "output", "metadata"}
|
|
88
|
+
|
|
81
89
|
|
|
82
90
|
@dataclasses.dataclass
|
|
83
91
|
class CreateSpanMessage(BaseMessage):
|
|
@@ -112,6 +120,10 @@ class CreateSpanMessage(BaseMessage):
|
|
|
112
120
|
data["total_estimated_cost"] = data.pop("total_cost")
|
|
113
121
|
return data
|
|
114
122
|
|
|
123
|
+
@staticmethod
|
|
124
|
+
def fields_to_anonymize() -> Set[str]:
|
|
125
|
+
return {"input", "output", "metadata"}
|
|
126
|
+
|
|
115
127
|
|
|
116
128
|
@dataclasses.dataclass
|
|
117
129
|
class UpdateSpanMessage(BaseMessage):
|
|
@@ -144,6 +156,10 @@ class UpdateSpanMessage(BaseMessage):
|
|
|
144
156
|
data["total_estimated_cost"] = data.pop("total_cost")
|
|
145
157
|
return data
|
|
146
158
|
|
|
159
|
+
@staticmethod
|
|
160
|
+
def fields_to_anonymize() -> Set[str]:
|
|
161
|
+
return {"input", "output", "metadata"}
|
|
162
|
+
|
|
147
163
|
|
|
148
164
|
@dataclasses.dataclass
|
|
149
165
|
class FeedbackScoreMessage(BaseMessage):
|
|
@@ -200,11 +216,19 @@ class AddThreadsFeedbackScoresBatchMessage(BaseMessage):
|
|
|
200
216
|
class CreateSpansBatchMessage(BaseMessage):
|
|
201
217
|
batch: List[span_write.SpanWrite]
|
|
202
218
|
|
|
219
|
+
@staticmethod
|
|
220
|
+
def fields_to_anonymize() -> Set[str]:
|
|
221
|
+
return {"input", "output", "metadata"}
|
|
222
|
+
|
|
203
223
|
|
|
204
224
|
@dataclasses.dataclass
|
|
205
225
|
class CreateTraceBatchMessage(BaseMessage):
|
|
206
226
|
batch: List[trace_write.TraceWrite]
|
|
207
227
|
|
|
228
|
+
@staticmethod
|
|
229
|
+
def fields_to_anonymize() -> Set[str]:
|
|
230
|
+
return {"input", "output", "metadata"}
|
|
231
|
+
|
|
208
232
|
|
|
209
233
|
@dataclasses.dataclass
|
|
210
234
|
class GuardrailBatchItemMessage(BaseMessage):
|
|
@@ -4,12 +4,11 @@ from typing import Callable, Dict, Type, Any
|
|
|
4
4
|
import pydantic
|
|
5
5
|
import tenacity
|
|
6
6
|
|
|
7
|
-
from . import messages, message_processors
|
|
7
|
+
from . import encoder_helpers, messages, message_processors
|
|
8
8
|
from .. import (
|
|
9
9
|
exceptions as exceptions,
|
|
10
10
|
logging_messages as logging_messages,
|
|
11
11
|
dict_utils,
|
|
12
|
-
jsonable_encoder,
|
|
13
12
|
)
|
|
14
13
|
from ..rate_limit import rate_limit
|
|
15
14
|
from ..rest_api import client as rest_api_client, core as rest_api_core
|
|
@@ -128,7 +127,12 @@ class OpikMessageProcessor(message_processors.BaseMessageProcessor):
|
|
|
128
127
|
cleaned_create_span_kwargs = dict_utils.remove_none_from_dict(
|
|
129
128
|
create_span_kwargs
|
|
130
129
|
)
|
|
131
|
-
cleaned_create_span_kwargs =
|
|
130
|
+
cleaned_create_span_kwargs = encoder_helpers.encode_and_anonymize(
|
|
131
|
+
cleaned_create_span_kwargs,
|
|
132
|
+
fields_to_anonymize=message.fields_to_anonymize(),
|
|
133
|
+
object_type="span",
|
|
134
|
+
)
|
|
135
|
+
|
|
132
136
|
LOGGER.debug("Create span request: %s", cleaned_create_span_kwargs)
|
|
133
137
|
self._rest_client.spans.create_span(**cleaned_create_span_kwargs)
|
|
134
138
|
|
|
@@ -140,9 +144,12 @@ class OpikMessageProcessor(message_processors.BaseMessageProcessor):
|
|
|
140
144
|
cleaned_create_trace_kwargs = dict_utils.remove_none_from_dict(
|
|
141
145
|
create_trace_kwargs
|
|
142
146
|
)
|
|
143
|
-
cleaned_create_trace_kwargs =
|
|
144
|
-
cleaned_create_trace_kwargs
|
|
147
|
+
cleaned_create_trace_kwargs = encoder_helpers.encode_and_anonymize(
|
|
148
|
+
cleaned_create_trace_kwargs,
|
|
149
|
+
fields_to_anonymize=message.fields_to_anonymize(),
|
|
150
|
+
object_type="trace",
|
|
145
151
|
)
|
|
152
|
+
|
|
146
153
|
LOGGER.debug("Create trace request: %s", cleaned_create_trace_kwargs)
|
|
147
154
|
self._rest_client.traces.create_trace(**cleaned_create_trace_kwargs)
|
|
148
155
|
|
|
@@ -155,7 +162,12 @@ class OpikMessageProcessor(message_processors.BaseMessageProcessor):
|
|
|
155
162
|
cleaned_update_span_kwargs = dict_utils.remove_none_from_dict(
|
|
156
163
|
update_span_kwargs
|
|
157
164
|
)
|
|
158
|
-
cleaned_update_span_kwargs =
|
|
165
|
+
cleaned_update_span_kwargs = encoder_helpers.encode_and_anonymize(
|
|
166
|
+
cleaned_update_span_kwargs,
|
|
167
|
+
fields_to_anonymize=message.fields_to_anonymize(),
|
|
168
|
+
object_type="span",
|
|
169
|
+
)
|
|
170
|
+
|
|
159
171
|
LOGGER.debug("Update span request: %s", cleaned_update_span_kwargs)
|
|
160
172
|
self._rest_client.spans.update_span(**cleaned_update_span_kwargs)
|
|
161
173
|
|
|
@@ -168,9 +180,12 @@ class OpikMessageProcessor(message_processors.BaseMessageProcessor):
|
|
|
168
180
|
cleaned_update_trace_kwargs = dict_utils.remove_none_from_dict(
|
|
169
181
|
update_trace_kwargs
|
|
170
182
|
)
|
|
171
|
-
cleaned_update_trace_kwargs =
|
|
172
|
-
cleaned_update_trace_kwargs
|
|
183
|
+
cleaned_update_trace_kwargs = encoder_helpers.encode_and_anonymize(
|
|
184
|
+
cleaned_update_trace_kwargs,
|
|
185
|
+
fields_to_anonymize=message.fields_to_anonymize(),
|
|
186
|
+
object_type="trace",
|
|
173
187
|
)
|
|
188
|
+
|
|
174
189
|
LOGGER.debug("Update trace request: %s", cleaned_update_trace_kwargs)
|
|
175
190
|
self._rest_client.traces.update_trace(**cleaned_update_trace_kwargs)
|
|
176
191
|
LOGGER.debug("Sent trace %s", message.trace_id)
|
opik/opik_context.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import contextlib
|
|
2
|
-
from typing import Any, Dict, List, Optional,
|
|
2
|
+
from typing import Any, Dict, List, Optional, Iterator, Union
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
from opik import llm_usage
|
|
5
5
|
from opik.api_objects import span, trace, opik_client, prompt
|
|
6
6
|
from opik.api_objects.attachment import Attachment
|
|
7
7
|
from opik.types import (
|
|
@@ -11,7 +11,7 @@ from opik.types import (
|
|
|
11
11
|
ErrorInfoDict,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
from opik import tracing_runtime_config
|
|
15
15
|
|
|
16
16
|
from . import context_storage, exceptions
|
|
17
17
|
from .decorator import error_info_collector
|
|
@@ -68,7 +68,7 @@ def update_current_span(
|
|
|
68
68
|
total_cost: Optional[float] = None,
|
|
69
69
|
attachments: Optional[List[Attachment]] = None,
|
|
70
70
|
error_info: Optional[ErrorInfoDict] = None,
|
|
71
|
-
prompts: Optional[List[prompt.
|
|
71
|
+
prompts: Optional[List[prompt.BasePrompt]] = None,
|
|
72
72
|
) -> None:
|
|
73
73
|
"""
|
|
74
74
|
Update the current span with the provided parameters. This method is usually called within a tracked function.
|
|
@@ -97,7 +97,7 @@ def update_current_span(
|
|
|
97
97
|
return
|
|
98
98
|
|
|
99
99
|
if prompts is not None:
|
|
100
|
-
prompts = [
|
|
100
|
+
prompts = [p.__internal_api__to_info_dict__() for p in prompts]
|
|
101
101
|
|
|
102
102
|
new_params = {
|
|
103
103
|
"name": name,
|
|
@@ -130,7 +130,7 @@ def update_current_trace(
|
|
|
130
130
|
feedback_scores: Optional[List[FeedbackScoreDict]] = None,
|
|
131
131
|
thread_id: Optional[str] = None,
|
|
132
132
|
attachments: Optional[List[Attachment]] = None,
|
|
133
|
-
prompts: Optional[List[prompt.
|
|
133
|
+
prompts: Optional[List[prompt.BasePrompt]] = None,
|
|
134
134
|
) -> None:
|
|
135
135
|
"""
|
|
136
136
|
Update the current trace with the provided parameters. This method is usually called within a tracked function.
|
|
@@ -151,7 +151,7 @@ def update_current_trace(
|
|
|
151
151
|
return
|
|
152
152
|
|
|
153
153
|
if prompts is not None:
|
|
154
|
-
prompts = [
|
|
154
|
+
prompts = [p.__internal_api__to_info_dict__() for p in prompts]
|
|
155
155
|
|
|
156
156
|
new_params = {
|
|
157
157
|
"name": name,
|