arize-phoenix 10.0.4__py3-none-any.whl → 12.28.1__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.
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/METADATA +124 -72
- arize_phoenix-12.28.1.dist-info/RECORD +499 -0
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/WHEEL +1 -1
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/IP_NOTICE +1 -1
- phoenix/__generated__/__init__.py +0 -0
- phoenix/__generated__/classification_evaluator_configs/__init__.py +20 -0
- phoenix/__generated__/classification_evaluator_configs/_document_relevance_classification_evaluator_config.py +17 -0
- phoenix/__generated__/classification_evaluator_configs/_hallucination_classification_evaluator_config.py +17 -0
- phoenix/__generated__/classification_evaluator_configs/_models.py +18 -0
- phoenix/__generated__/classification_evaluator_configs/_tool_selection_classification_evaluator_config.py +17 -0
- phoenix/__init__.py +5 -4
- phoenix/auth.py +39 -2
- phoenix/config.py +1763 -91
- phoenix/datetime_utils.py +120 -2
- phoenix/db/README.md +595 -25
- phoenix/db/bulk_inserter.py +145 -103
- phoenix/db/engines.py +140 -33
- phoenix/db/enums.py +3 -12
- phoenix/db/facilitator.py +302 -35
- phoenix/db/helpers.py +1000 -65
- phoenix/db/iam_auth.py +64 -0
- phoenix/db/insertion/dataset.py +135 -2
- phoenix/db/insertion/document_annotation.py +9 -6
- phoenix/db/insertion/evaluation.py +2 -3
- phoenix/db/insertion/helpers.py +17 -2
- phoenix/db/insertion/session_annotation.py +176 -0
- phoenix/db/insertion/span.py +15 -11
- phoenix/db/insertion/span_annotation.py +3 -4
- phoenix/db/insertion/trace_annotation.py +3 -4
- phoenix/db/insertion/types.py +50 -20
- phoenix/db/migrations/versions/01a8342c9cdf_add_user_id_on_datasets.py +40 -0
- phoenix/db/migrations/versions/0df286449799_add_session_annotations_table.py +105 -0
- phoenix/db/migrations/versions/272b66ff50f8_drop_single_indices.py +119 -0
- phoenix/db/migrations/versions/58228d933c91_dataset_labels.py +67 -0
- phoenix/db/migrations/versions/699f655af132_experiment_tags.py +57 -0
- phoenix/db/migrations/versions/735d3d93c33e_add_composite_indices.py +41 -0
- phoenix/db/migrations/versions/a20694b15f82_cost.py +196 -0
- phoenix/db/migrations/versions/ab513d89518b_add_user_id_on_dataset_versions.py +40 -0
- phoenix/db/migrations/versions/d0690a79ea51_users_on_experiments.py +40 -0
- phoenix/db/migrations/versions/deb2c81c0bb2_dataset_splits.py +139 -0
- phoenix/db/migrations/versions/e76cbd66ffc3_add_experiments_dataset_examples.py +87 -0
- phoenix/db/models.py +669 -56
- phoenix/db/pg_config.py +10 -0
- phoenix/db/types/model_provider.py +4 -0
- phoenix/db/types/token_price_customization.py +29 -0
- phoenix/db/types/trace_retention.py +23 -15
- phoenix/experiments/evaluators/utils.py +3 -3
- phoenix/experiments/functions.py +160 -52
- phoenix/experiments/tracing.py +2 -2
- phoenix/experiments/types.py +1 -1
- phoenix/inferences/inferences.py +1 -2
- phoenix/server/api/auth.py +38 -7
- phoenix/server/api/auth_messages.py +46 -0
- phoenix/server/api/context.py +100 -4
- phoenix/server/api/dataloaders/__init__.py +79 -5
- phoenix/server/api/dataloaders/annotation_configs_by_project.py +31 -0
- phoenix/server/api/dataloaders/annotation_summaries.py +60 -8
- phoenix/server/api/dataloaders/average_experiment_repeated_run_group_latency.py +50 -0
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +17 -24
- phoenix/server/api/dataloaders/cache/two_tier_cache.py +1 -2
- phoenix/server/api/dataloaders/dataset_dataset_splits.py +52 -0
- phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -1
- phoenix/server/api/dataloaders/dataset_example_splits.py +40 -0
- phoenix/server/api/dataloaders/dataset_examples_and_versions_by_experiment_run.py +47 -0
- phoenix/server/api/dataloaders/dataset_labels.py +36 -0
- phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -2
- phoenix/server/api/dataloaders/document_evaluations.py +6 -9
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +88 -34
- phoenix/server/api/dataloaders/experiment_dataset_splits.py +43 -0
- phoenix/server/api/dataloaders/experiment_error_rates.py +21 -28
- phoenix/server/api/dataloaders/experiment_repeated_run_group_annotation_summaries.py +77 -0
- phoenix/server/api/dataloaders/experiment_repeated_run_groups.py +57 -0
- phoenix/server/api/dataloaders/experiment_runs_by_experiment_and_example.py +44 -0
- phoenix/server/api/dataloaders/last_used_times_by_generative_model_id.py +35 -0
- phoenix/server/api/dataloaders/latency_ms_quantile.py +40 -8
- phoenix/server/api/dataloaders/record_counts.py +37 -10
- phoenix/server/api/dataloaders/session_annotations_by_session.py +29 -0
- phoenix/server/api/dataloaders/span_cost_by_span.py +24 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_generative_model.py +56 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_project_session.py +57 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_span.py +43 -0
- phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_trace.py +56 -0
- phoenix/server/api/dataloaders/span_cost_details_by_span_cost.py +27 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment.py +57 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment_repeated_run_group.py +64 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_experiment_run.py +58 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_generative_model.py +55 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_project.py +152 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_project_session.py +56 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_trace.py +55 -0
- phoenix/server/api/dataloaders/span_costs.py +29 -0
- phoenix/server/api/dataloaders/table_fields.py +2 -2
- phoenix/server/api/dataloaders/token_prices_by_model.py +30 -0
- phoenix/server/api/dataloaders/trace_annotations_by_trace.py +27 -0
- phoenix/server/api/dataloaders/types.py +29 -0
- phoenix/server/api/exceptions.py +11 -1
- phoenix/server/api/helpers/dataset_helpers.py +5 -1
- phoenix/server/api/helpers/playground_clients.py +1243 -292
- phoenix/server/api/helpers/playground_registry.py +2 -2
- phoenix/server/api/helpers/playground_spans.py +8 -4
- phoenix/server/api/helpers/playground_users.py +26 -0
- phoenix/server/api/helpers/prompts/conversions/aws.py +83 -0
- phoenix/server/api/helpers/prompts/conversions/google.py +103 -0
- phoenix/server/api/helpers/prompts/models.py +205 -22
- phoenix/server/api/input_types/{SpanAnnotationFilter.py → AnnotationFilter.py} +22 -14
- phoenix/server/api/input_types/ChatCompletionInput.py +6 -2
- phoenix/server/api/input_types/CreateProjectInput.py +27 -0
- phoenix/server/api/input_types/CreateProjectSessionAnnotationInput.py +37 -0
- phoenix/server/api/input_types/DatasetFilter.py +17 -0
- phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
- phoenix/server/api/input_types/GenerativeCredentialInput.py +9 -0
- phoenix/server/api/input_types/GenerativeModelInput.py +5 -0
- phoenix/server/api/input_types/ProjectSessionSort.py +161 -1
- phoenix/server/api/input_types/PromptFilter.py +14 -0
- phoenix/server/api/input_types/PromptVersionInput.py +52 -1
- phoenix/server/api/input_types/SpanSort.py +44 -7
- phoenix/server/api/input_types/TimeBinConfig.py +23 -0
- phoenix/server/api/input_types/UpdateAnnotationInput.py +34 -0
- phoenix/server/api/input_types/UserRoleInput.py +1 -0
- phoenix/server/api/mutations/__init__.py +10 -0
- phoenix/server/api/mutations/annotation_config_mutations.py +8 -8
- phoenix/server/api/mutations/api_key_mutations.py +19 -23
- phoenix/server/api/mutations/chat_mutations.py +154 -47
- phoenix/server/api/mutations/dataset_label_mutations.py +243 -0
- phoenix/server/api/mutations/dataset_mutations.py +21 -16
- phoenix/server/api/mutations/dataset_split_mutations.py +351 -0
- phoenix/server/api/mutations/experiment_mutations.py +2 -2
- phoenix/server/api/mutations/export_events_mutations.py +3 -3
- phoenix/server/api/mutations/model_mutations.py +210 -0
- phoenix/server/api/mutations/project_mutations.py +49 -10
- phoenix/server/api/mutations/project_session_annotations_mutations.py +158 -0
- phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +8 -4
- phoenix/server/api/mutations/prompt_label_mutations.py +74 -65
- phoenix/server/api/mutations/prompt_mutations.py +65 -129
- phoenix/server/api/mutations/prompt_version_tag_mutations.py +11 -8
- phoenix/server/api/mutations/span_annotations_mutations.py +15 -10
- phoenix/server/api/mutations/trace_annotations_mutations.py +14 -10
- phoenix/server/api/mutations/trace_mutations.py +47 -3
- phoenix/server/api/mutations/user_mutations.py +66 -41
- phoenix/server/api/queries.py +768 -293
- phoenix/server/api/routers/__init__.py +2 -2
- phoenix/server/api/routers/auth.py +154 -88
- phoenix/server/api/routers/ldap.py +229 -0
- phoenix/server/api/routers/oauth2.py +369 -106
- phoenix/server/api/routers/v1/__init__.py +24 -4
- phoenix/server/api/routers/v1/annotation_configs.py +23 -31
- phoenix/server/api/routers/v1/annotations.py +481 -17
- phoenix/server/api/routers/v1/datasets.py +395 -81
- phoenix/server/api/routers/v1/documents.py +142 -0
- phoenix/server/api/routers/v1/evaluations.py +24 -31
- phoenix/server/api/routers/v1/experiment_evaluations.py +19 -8
- phoenix/server/api/routers/v1/experiment_runs.py +337 -59
- phoenix/server/api/routers/v1/experiments.py +479 -48
- phoenix/server/api/routers/v1/models.py +7 -0
- phoenix/server/api/routers/v1/projects.py +18 -49
- phoenix/server/api/routers/v1/prompts.py +54 -40
- phoenix/server/api/routers/v1/sessions.py +108 -0
- phoenix/server/api/routers/v1/spans.py +1091 -81
- phoenix/server/api/routers/v1/traces.py +132 -78
- phoenix/server/api/routers/v1/users.py +389 -0
- phoenix/server/api/routers/v1/utils.py +3 -7
- phoenix/server/api/subscriptions.py +305 -88
- phoenix/server/api/types/Annotation.py +90 -23
- phoenix/server/api/types/ApiKey.py +13 -17
- phoenix/server/api/types/AuthMethod.py +1 -0
- phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +1 -0
- phoenix/server/api/types/CostBreakdown.py +12 -0
- phoenix/server/api/types/Dataset.py +226 -72
- phoenix/server/api/types/DatasetExample.py +88 -18
- phoenix/server/api/types/DatasetExperimentAnnotationSummary.py +10 -0
- phoenix/server/api/types/DatasetLabel.py +57 -0
- phoenix/server/api/types/DatasetSplit.py +98 -0
- phoenix/server/api/types/DatasetVersion.py +49 -4
- phoenix/server/api/types/DocumentAnnotation.py +212 -0
- phoenix/server/api/types/Experiment.py +264 -59
- phoenix/server/api/types/ExperimentComparison.py +5 -10
- phoenix/server/api/types/ExperimentRepeatedRunGroup.py +155 -0
- phoenix/server/api/types/ExperimentRepeatedRunGroupAnnotationSummary.py +9 -0
- phoenix/server/api/types/ExperimentRun.py +169 -65
- phoenix/server/api/types/ExperimentRunAnnotation.py +158 -39
- phoenix/server/api/types/GenerativeModel.py +245 -3
- phoenix/server/api/types/GenerativeProvider.py +70 -11
- phoenix/server/api/types/{Model.py → InferenceModel.py} +1 -1
- phoenix/server/api/types/ModelInterface.py +16 -0
- phoenix/server/api/types/PlaygroundModel.py +20 -0
- phoenix/server/api/types/Project.py +1278 -216
- phoenix/server/api/types/ProjectSession.py +188 -28
- phoenix/server/api/types/ProjectSessionAnnotation.py +187 -0
- phoenix/server/api/types/ProjectTraceRetentionPolicy.py +1 -1
- phoenix/server/api/types/Prompt.py +119 -39
- phoenix/server/api/types/PromptLabel.py +42 -25
- phoenix/server/api/types/PromptVersion.py +11 -8
- phoenix/server/api/types/PromptVersionTag.py +65 -25
- phoenix/server/api/types/ServerStatus.py +6 -0
- phoenix/server/api/types/Span.py +167 -123
- phoenix/server/api/types/SpanAnnotation.py +189 -42
- phoenix/server/api/types/SpanCostDetailSummaryEntry.py +10 -0
- phoenix/server/api/types/SpanCostSummary.py +10 -0
- phoenix/server/api/types/SystemApiKey.py +65 -1
- phoenix/server/api/types/TokenPrice.py +16 -0
- phoenix/server/api/types/TokenUsage.py +3 -3
- phoenix/server/api/types/Trace.py +223 -51
- phoenix/server/api/types/TraceAnnotation.py +149 -50
- phoenix/server/api/types/User.py +137 -32
- phoenix/server/api/types/UserApiKey.py +73 -26
- phoenix/server/api/types/node.py +10 -0
- phoenix/server/api/types/pagination.py +11 -2
- phoenix/server/app.py +290 -45
- phoenix/server/authorization.py +38 -3
- phoenix/server/bearer_auth.py +34 -24
- phoenix/server/cost_tracking/cost_details_calculator.py +196 -0
- phoenix/server/cost_tracking/cost_model_lookup.py +179 -0
- phoenix/server/cost_tracking/helpers.py +68 -0
- phoenix/server/cost_tracking/model_cost_manifest.json +3657 -830
- phoenix/server/cost_tracking/regex_specificity.py +397 -0
- phoenix/server/cost_tracking/token_cost_calculator.py +57 -0
- phoenix/server/daemons/__init__.py +0 -0
- phoenix/server/daemons/db_disk_usage_monitor.py +214 -0
- phoenix/server/daemons/generative_model_store.py +103 -0
- phoenix/server/daemons/span_cost_calculator.py +99 -0
- phoenix/server/dml_event.py +17 -0
- phoenix/server/dml_event_handler.py +5 -0
- phoenix/server/email/sender.py +56 -3
- phoenix/server/email/templates/db_disk_usage_notification.html +19 -0
- phoenix/server/email/types.py +11 -0
- phoenix/server/experiments/__init__.py +0 -0
- phoenix/server/experiments/utils.py +14 -0
- phoenix/server/grpc_server.py +11 -11
- phoenix/server/jwt_store.py +17 -15
- phoenix/server/ldap.py +1449 -0
- phoenix/server/main.py +26 -10
- phoenix/server/oauth2.py +330 -12
- phoenix/server/prometheus.py +66 -6
- phoenix/server/rate_limiters.py +4 -9
- phoenix/server/retention.py +33 -20
- phoenix/server/session_filters.py +49 -0
- phoenix/server/static/.vite/manifest.json +55 -51
- phoenix/server/static/assets/components-BreFUQQa.js +6702 -0
- phoenix/server/static/assets/{index-E0M82BdE.js → index-CTQoemZv.js} +140 -56
- phoenix/server/static/assets/pages-DBE5iYM3.js +9524 -0
- phoenix/server/static/assets/vendor-BGzfc4EU.css +1 -0
- phoenix/server/static/assets/vendor-DCE4v-Ot.js +920 -0
- phoenix/server/static/assets/vendor-codemirror-D5f205eT.js +25 -0
- phoenix/server/static/assets/vendor-recharts-V9cwpXsm.js +37 -0
- phoenix/server/static/assets/vendor-shiki-Do--csgv.js +5 -0
- phoenix/server/static/assets/vendor-three-CmB8bl_y.js +3840 -0
- phoenix/server/templates/index.html +40 -6
- phoenix/server/thread_server.py +1 -2
- phoenix/server/types.py +14 -4
- phoenix/server/utils.py +74 -0
- phoenix/session/client.py +56 -3
- phoenix/session/data_extractor.py +5 -0
- phoenix/session/evaluation.py +14 -5
- phoenix/session/session.py +45 -9
- phoenix/settings.py +5 -0
- phoenix/trace/attributes.py +80 -13
- phoenix/trace/dsl/helpers.py +90 -1
- phoenix/trace/dsl/query.py +8 -6
- phoenix/trace/projects.py +5 -0
- phoenix/utilities/template_formatters.py +1 -1
- phoenix/version.py +1 -1
- arize_phoenix-10.0.4.dist-info/RECORD +0 -405
- phoenix/server/api/types/Evaluation.py +0 -39
- phoenix/server/cost_tracking/cost_lookup.py +0 -255
- phoenix/server/static/assets/components-DULKeDfL.js +0 -4365
- phoenix/server/static/assets/pages-Cl0A-0U2.js +0 -7430
- phoenix/server/static/assets/vendor-WIZid84E.css +0 -1
- phoenix/server/static/assets/vendor-arizeai-Dy-0mSNw.js +0 -649
- phoenix/server/static/assets/vendor-codemirror-DBtifKNr.js +0 -33
- phoenix/server/static/assets/vendor-oB4u9zuV.js +0 -905
- phoenix/server/static/assets/vendor-recharts-D-T4KPz2.js +0 -59
- phoenix/server/static/assets/vendor-shiki-BMn4O_9F.js +0 -5
- phoenix/server/static/assets/vendor-three-C5WAXd5r.js +0 -2998
- phoenix/utilities/deprecation.py +0 -31
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-10.0.4.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/LICENSE +0 -0
phoenix/server/api/types/Span.py
CHANGED
|
@@ -23,24 +23,27 @@ from phoenix.server.api.helpers.dataset_helpers import (
|
|
|
23
23
|
get_dataset_example_input,
|
|
24
24
|
get_dataset_example_output,
|
|
25
25
|
)
|
|
26
|
-
from phoenix.server.api.input_types.
|
|
27
|
-
|
|
28
|
-
SpanAnnotationFilter,
|
|
26
|
+
from phoenix.server.api.input_types.AnnotationFilter import (
|
|
27
|
+
AnnotationFilter,
|
|
29
28
|
satisfies_filter,
|
|
30
29
|
)
|
|
30
|
+
from phoenix.server.api.input_types.InvocationParameters import InvocationParameter
|
|
31
31
|
from phoenix.server.api.input_types.SpanAnnotationSort import (
|
|
32
32
|
SpanAnnotationColumn,
|
|
33
33
|
SpanAnnotationSort,
|
|
34
34
|
)
|
|
35
35
|
from phoenix.server.api.types.AnnotationSummary import AnnotationSummary
|
|
36
|
+
from phoenix.server.api.types.CostBreakdown import CostBreakdown
|
|
37
|
+
from phoenix.server.api.types.DocumentAnnotation import DocumentAnnotation
|
|
36
38
|
from phoenix.server.api.types.DocumentRetrievalMetrics import DocumentRetrievalMetrics
|
|
37
|
-
from phoenix.server.api.types.Evaluation import DocumentEvaluation
|
|
38
39
|
from phoenix.server.api.types.ExampleRevisionInterface import ExampleRevision
|
|
39
40
|
from phoenix.server.api.types.GenerativeProvider import GenerativeProvider
|
|
40
41
|
from phoenix.server.api.types.MimeType import MimeType
|
|
41
42
|
from phoenix.server.api.types.pagination import ConnectionArgs, CursorString, connection_from_list
|
|
42
43
|
from phoenix.server.api.types.SortDir import SortDir
|
|
43
|
-
from phoenix.server.api.types.SpanAnnotation import SpanAnnotation
|
|
44
|
+
from phoenix.server.api.types.SpanAnnotation import SpanAnnotation
|
|
45
|
+
from phoenix.server.api.types.SpanCostDetailSummaryEntry import SpanCostDetailSummaryEntry
|
|
46
|
+
from phoenix.server.api.types.SpanCostSummary import SpanCostSummary
|
|
44
47
|
from phoenix.server.api.types.SpanIOValue import SpanIOValue, truncate_value
|
|
45
48
|
from phoenix.trace.attributes import get_attribute_value
|
|
46
49
|
|
|
@@ -120,11 +123,11 @@ SpanRowId: TypeAlias = int
|
|
|
120
123
|
|
|
121
124
|
@strawberry.type
|
|
122
125
|
class Span(Node):
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
id: NodeID[SpanRowId]
|
|
127
|
+
db_record: strawberry.Private[Optional[models.Span]] = None
|
|
125
128
|
|
|
126
129
|
def __post_init__(self) -> None:
|
|
127
|
-
if self.
|
|
130
|
+
if self.db_record and self.id != self.db_record.id:
|
|
128
131
|
raise ValueError("Span ID mismatch")
|
|
129
132
|
|
|
130
133
|
@strawberry.field
|
|
@@ -132,10 +135,10 @@ class Span(Node):
|
|
|
132
135
|
self,
|
|
133
136
|
info: Info[Context, None],
|
|
134
137
|
) -> str:
|
|
135
|
-
if self.
|
|
136
|
-
return self.
|
|
138
|
+
if self.db_record:
|
|
139
|
+
return self.db_record.name
|
|
137
140
|
value = await info.context.data_loaders.span_fields.load(
|
|
138
|
-
(self.
|
|
141
|
+
(self.id, models.Span.name),
|
|
139
142
|
)
|
|
140
143
|
return str(value)
|
|
141
144
|
|
|
@@ -144,11 +147,11 @@ class Span(Node):
|
|
|
144
147
|
self,
|
|
145
148
|
info: Info[Context, None],
|
|
146
149
|
) -> SpanStatusCode:
|
|
147
|
-
if self.
|
|
148
|
-
value = self.
|
|
150
|
+
if self.db_record:
|
|
151
|
+
value = self.db_record.status_code
|
|
149
152
|
else:
|
|
150
153
|
value = await info.context.data_loaders.span_fields.load(
|
|
151
|
-
(self.
|
|
154
|
+
(self.id, models.Span.status_code),
|
|
152
155
|
)
|
|
153
156
|
return SpanStatusCode(value)
|
|
154
157
|
|
|
@@ -157,10 +160,10 @@ class Span(Node):
|
|
|
157
160
|
self,
|
|
158
161
|
info: Info[Context, None],
|
|
159
162
|
) -> str:
|
|
160
|
-
if self.
|
|
161
|
-
return self.
|
|
163
|
+
if self.db_record:
|
|
164
|
+
return self.db_record.status_message
|
|
162
165
|
value = await info.context.data_loaders.span_fields.load(
|
|
163
|
-
(self.
|
|
166
|
+
(self.id, models.Span.status_message),
|
|
164
167
|
)
|
|
165
168
|
return str(value)
|
|
166
169
|
|
|
@@ -169,10 +172,10 @@ class Span(Node):
|
|
|
169
172
|
self,
|
|
170
173
|
info: Info[Context, None],
|
|
171
174
|
) -> datetime:
|
|
172
|
-
if self.
|
|
173
|
-
return self.
|
|
175
|
+
if self.db_record:
|
|
176
|
+
return self.db_record.start_time
|
|
174
177
|
value = await info.context.data_loaders.span_fields.load(
|
|
175
|
-
(self.
|
|
178
|
+
(self.id, models.Span.start_time),
|
|
176
179
|
)
|
|
177
180
|
return cast(datetime, value)
|
|
178
181
|
|
|
@@ -181,10 +184,10 @@ class Span(Node):
|
|
|
181
184
|
self,
|
|
182
185
|
info: Info[Context, None],
|
|
183
186
|
) -> Optional[datetime]:
|
|
184
|
-
if self.
|
|
185
|
-
return self.
|
|
187
|
+
if self.db_record:
|
|
188
|
+
return self.db_record.end_time
|
|
186
189
|
value = await info.context.data_loaders.span_fields.load(
|
|
187
|
-
(self.
|
|
190
|
+
(self.id, models.Span.end_time),
|
|
188
191
|
)
|
|
189
192
|
return cast(datetime, value)
|
|
190
193
|
|
|
@@ -193,10 +196,10 @@ class Span(Node):
|
|
|
193
196
|
self,
|
|
194
197
|
info: Info[Context, None],
|
|
195
198
|
) -> Optional[float]:
|
|
196
|
-
if self.
|
|
197
|
-
return self.
|
|
199
|
+
if self.db_record:
|
|
200
|
+
return self.db_record.latency_ms
|
|
198
201
|
value = await info.context.data_loaders.span_fields.load(
|
|
199
|
-
(self.
|
|
202
|
+
(self.id, models.Span.latency_ms),
|
|
200
203
|
)
|
|
201
204
|
return cast(float, value)
|
|
202
205
|
|
|
@@ -207,11 +210,11 @@ class Span(Node):
|
|
|
207
210
|
self,
|
|
208
211
|
info: Info[Context, None],
|
|
209
212
|
) -> Optional[ID]:
|
|
210
|
-
if self.
|
|
211
|
-
value = self.
|
|
213
|
+
if self.db_record:
|
|
214
|
+
value = self.db_record.parent_id
|
|
212
215
|
else:
|
|
213
216
|
value = await info.context.data_loaders.span_fields.load(
|
|
214
|
-
(self.
|
|
217
|
+
(self.id, models.Span.parent_id),
|
|
215
218
|
)
|
|
216
219
|
return None if value is None else ID(value)
|
|
217
220
|
|
|
@@ -220,11 +223,11 @@ class Span(Node):
|
|
|
220
223
|
self,
|
|
221
224
|
info: Info[Context, None],
|
|
222
225
|
) -> SpanKind:
|
|
223
|
-
if self.
|
|
224
|
-
value = self.
|
|
226
|
+
if self.db_record:
|
|
227
|
+
value = self.db_record.span_kind
|
|
225
228
|
else:
|
|
226
229
|
value = await info.context.data_loaders.span_fields.load(
|
|
227
|
-
(self.
|
|
230
|
+
(self.id, models.Span.span_kind),
|
|
228
231
|
)
|
|
229
232
|
return SpanKind(value)
|
|
230
233
|
|
|
@@ -233,11 +236,11 @@ class Span(Node):
|
|
|
233
236
|
self,
|
|
234
237
|
info: Info[Context, None],
|
|
235
238
|
) -> ID:
|
|
236
|
-
if self.
|
|
237
|
-
span_id = self.
|
|
239
|
+
if self.db_record:
|
|
240
|
+
span_id = self.db_record.span_id
|
|
238
241
|
else:
|
|
239
242
|
span_id = await info.context.data_loaders.span_fields.load(
|
|
240
|
-
(self.
|
|
243
|
+
(self.id, models.Span.span_id),
|
|
241
244
|
)
|
|
242
245
|
return ID(span_id)
|
|
243
246
|
|
|
@@ -246,31 +249,31 @@ class Span(Node):
|
|
|
246
249
|
self,
|
|
247
250
|
info: Info[Context, None],
|
|
248
251
|
) -> Annotated["Trace", strawberry.lazy(".Trace")]:
|
|
249
|
-
if self.
|
|
250
|
-
trace_rowid = self.
|
|
252
|
+
if self.db_record:
|
|
253
|
+
trace_rowid = self.db_record.trace_rowid
|
|
251
254
|
else:
|
|
252
255
|
trace_rowid = await info.context.data_loaders.span_fields.load(
|
|
253
|
-
(self.
|
|
256
|
+
(self.id, models.Span.trace_rowid),
|
|
254
257
|
)
|
|
255
258
|
from phoenix.server.api.types.Trace import Trace
|
|
256
259
|
|
|
257
|
-
return Trace(
|
|
260
|
+
return Trace(id=trace_rowid)
|
|
258
261
|
|
|
259
262
|
@strawberry.field
|
|
260
263
|
async def context(
|
|
261
264
|
self,
|
|
262
265
|
info: Info[Context, None],
|
|
263
266
|
) -> SpanContext:
|
|
264
|
-
if self.
|
|
265
|
-
trace_id = self.
|
|
266
|
-
span_id = self.
|
|
267
|
+
if self.db_record:
|
|
268
|
+
trace_id = self.db_record.trace.trace_id
|
|
269
|
+
span_id = self.db_record.span_id
|
|
267
270
|
else:
|
|
268
271
|
span_id, trace_id = await gather(
|
|
269
272
|
info.context.data_loaders.span_fields.load(
|
|
270
|
-
(self.
|
|
273
|
+
(self.id, models.Span.span_id),
|
|
271
274
|
),
|
|
272
275
|
info.context.data_loaders.span_fields.load(
|
|
273
|
-
(self.
|
|
276
|
+
(self.id, models.Trace.trace_id),
|
|
274
277
|
),
|
|
275
278
|
)
|
|
276
279
|
return SpanContext(trace_id=ID(trace_id), span_id=ID(span_id))
|
|
@@ -282,11 +285,11 @@ class Span(Node):
|
|
|
282
285
|
self,
|
|
283
286
|
info: Info[Context, None],
|
|
284
287
|
) -> str:
|
|
285
|
-
if self.
|
|
286
|
-
value = self.
|
|
288
|
+
if self.db_record:
|
|
289
|
+
value = self.db_record.attributes
|
|
287
290
|
else:
|
|
288
291
|
value = await info.context.data_loaders.span_fields.load(
|
|
289
|
-
(self.
|
|
292
|
+
(self.id, models.Span.attributes),
|
|
290
293
|
)
|
|
291
294
|
return json.dumps(_hide_embedding_vectors(value), cls=_JSONEncoder)
|
|
292
295
|
|
|
@@ -297,11 +300,11 @@ class Span(Node):
|
|
|
297
300
|
self,
|
|
298
301
|
info: Info[Context, None],
|
|
299
302
|
) -> Optional[str]:
|
|
300
|
-
if self.
|
|
301
|
-
value = self.
|
|
303
|
+
if self.db_record:
|
|
304
|
+
value = self.db_record.metadata_
|
|
302
305
|
else:
|
|
303
306
|
value = await info.context.data_loaders.span_fields.load(
|
|
304
|
-
(self.
|
|
307
|
+
(self.id, models.Span.metadata_),
|
|
305
308
|
)
|
|
306
309
|
return _convert_metadata_to_string(value)
|
|
307
310
|
|
|
@@ -310,10 +313,10 @@ class Span(Node):
|
|
|
310
313
|
self,
|
|
311
314
|
info: Info[Context, None],
|
|
312
315
|
) -> Optional[int]:
|
|
313
|
-
if self.
|
|
314
|
-
return self.
|
|
316
|
+
if self.db_record:
|
|
317
|
+
return self.db_record.num_documents
|
|
315
318
|
value = await info.context.data_loaders.span_fields.load(
|
|
316
|
-
(self.
|
|
319
|
+
(self.id, models.Span.num_documents),
|
|
317
320
|
)
|
|
318
321
|
return cast(int, value)
|
|
319
322
|
|
|
@@ -322,10 +325,10 @@ class Span(Node):
|
|
|
322
325
|
self,
|
|
323
326
|
info: Info[Context, None],
|
|
324
327
|
) -> Optional[int]:
|
|
325
|
-
if self.
|
|
326
|
-
return self.
|
|
328
|
+
if self.db_record:
|
|
329
|
+
return self.db_record.llm_token_count_total
|
|
327
330
|
value = await info.context.data_loaders.span_fields.load(
|
|
328
|
-
(self.
|
|
331
|
+
(self.id, models.Span.llm_token_count_total),
|
|
329
332
|
)
|
|
330
333
|
return cast(Optional[int], value)
|
|
331
334
|
|
|
@@ -334,10 +337,10 @@ class Span(Node):
|
|
|
334
337
|
self,
|
|
335
338
|
info: Info[Context, None],
|
|
336
339
|
) -> Optional[int]:
|
|
337
|
-
if self.
|
|
338
|
-
return self.
|
|
340
|
+
if self.db_record:
|
|
341
|
+
return self.db_record.llm_token_count_prompt
|
|
339
342
|
value = await info.context.data_loaders.span_fields.load(
|
|
340
|
-
(self.
|
|
343
|
+
(self.id, models.Span.llm_token_count_prompt),
|
|
341
344
|
)
|
|
342
345
|
return cast(Optional[int], value)
|
|
343
346
|
|
|
@@ -346,10 +349,10 @@ class Span(Node):
|
|
|
346
349
|
self,
|
|
347
350
|
info: Info[Context, None],
|
|
348
351
|
) -> Optional[int]:
|
|
349
|
-
if self.
|
|
350
|
-
return self.
|
|
352
|
+
if self.db_record:
|
|
353
|
+
return self.db_record.llm_token_count_completion
|
|
351
354
|
value = await info.context.data_loaders.span_fields.load(
|
|
352
|
-
(self.
|
|
355
|
+
(self.id, models.Span.llm_token_count_completion),
|
|
353
356
|
)
|
|
354
357
|
return cast(Optional[int], value)
|
|
355
358
|
|
|
@@ -358,11 +361,11 @@ class Span(Node):
|
|
|
358
361
|
self,
|
|
359
362
|
info: Info[Context, None],
|
|
360
363
|
) -> TokenCountPromptDetails:
|
|
361
|
-
if self.
|
|
362
|
-
attributes = self.
|
|
364
|
+
if self.db_record:
|
|
365
|
+
attributes = self.db_record.attributes
|
|
363
366
|
else:
|
|
364
367
|
attributes = await info.context.data_loaders.span_fields.load(
|
|
365
|
-
(self.
|
|
368
|
+
(self.id, models.Span.attributes),
|
|
366
369
|
)
|
|
367
370
|
|
|
368
371
|
cache_read: Optional[int] = None
|
|
@@ -400,28 +403,28 @@ class Span(Node):
|
|
|
400
403
|
self,
|
|
401
404
|
info: Info[Context, None],
|
|
402
405
|
) -> Optional[SpanIOValue]:
|
|
403
|
-
if self.
|
|
404
|
-
input_value = self.
|
|
406
|
+
if self.db_record:
|
|
407
|
+
input_value = self.db_record.input_value
|
|
405
408
|
if input_value is None or input_value == "":
|
|
406
409
|
return None
|
|
407
410
|
input_value = str(input_value)
|
|
408
|
-
mime_type = self.
|
|
411
|
+
mime_type = self.db_record.input_mime_type
|
|
409
412
|
return SpanIOValue(
|
|
410
413
|
cached_value=input_value,
|
|
411
414
|
mime_type=MimeType(mime_type),
|
|
412
415
|
)
|
|
413
416
|
mime_type, input_value_first_101_chars = await gather(
|
|
414
417
|
info.context.data_loaders.span_fields.load(
|
|
415
|
-
(self.
|
|
418
|
+
(self.id, models.Span.input_mime_type),
|
|
416
419
|
),
|
|
417
420
|
info.context.data_loaders.span_fields.load(
|
|
418
|
-
(self.
|
|
421
|
+
(self.id, models.Span.input_value_first_101_chars),
|
|
419
422
|
),
|
|
420
423
|
)
|
|
421
424
|
if not input_value_first_101_chars:
|
|
422
425
|
return None
|
|
423
426
|
return SpanIOValue(
|
|
424
|
-
span_rowid=self.
|
|
427
|
+
span_rowid=self.id,
|
|
425
428
|
attr=models.Span.input_value,
|
|
426
429
|
truncated_value=truncate_value(input_value_first_101_chars),
|
|
427
430
|
mime_type=MimeType(mime_type),
|
|
@@ -432,28 +435,28 @@ class Span(Node):
|
|
|
432
435
|
self,
|
|
433
436
|
info: Info[Context, None],
|
|
434
437
|
) -> Optional[SpanIOValue]:
|
|
435
|
-
if self.
|
|
436
|
-
output_value = self.
|
|
438
|
+
if self.db_record:
|
|
439
|
+
output_value = self.db_record.output_value
|
|
437
440
|
if output_value is None or output_value == "":
|
|
438
441
|
return None
|
|
439
442
|
output_value = str(output_value)
|
|
440
|
-
mime_type = self.
|
|
443
|
+
mime_type = self.db_record.output_mime_type
|
|
441
444
|
return SpanIOValue(
|
|
442
445
|
cached_value=output_value,
|
|
443
446
|
mime_type=MimeType(mime_type),
|
|
444
447
|
)
|
|
445
448
|
mime_type, output_value_first_101_chars = await gather(
|
|
446
449
|
info.context.data_loaders.span_fields.load(
|
|
447
|
-
(self.
|
|
450
|
+
(self.id, models.Span.output_mime_type),
|
|
448
451
|
),
|
|
449
452
|
info.context.data_loaders.span_fields.load(
|
|
450
|
-
(self.
|
|
453
|
+
(self.id, models.Span.output_value_first_101_chars),
|
|
451
454
|
),
|
|
452
455
|
)
|
|
453
456
|
if not output_value_first_101_chars:
|
|
454
457
|
return None
|
|
455
458
|
return SpanIOValue(
|
|
456
|
-
span_rowid=self.
|
|
459
|
+
span_rowid=self.id,
|
|
457
460
|
attr=models.Span.output_value,
|
|
458
461
|
truncated_value=truncate_value(output_value_first_101_chars),
|
|
459
462
|
mime_type=MimeType(mime_type),
|
|
@@ -464,10 +467,10 @@ class Span(Node):
|
|
|
464
467
|
self,
|
|
465
468
|
info: Info[Context, None],
|
|
466
469
|
) -> list[SpanEvent]:
|
|
467
|
-
if self.
|
|
468
|
-
return [SpanEvent.from_dict(event) for event in self.
|
|
470
|
+
if self.db_record:
|
|
471
|
+
return [SpanEvent.from_dict(event) for event in self.db_record.events]
|
|
469
472
|
value = await info.context.data_loaders.span_fields.load(
|
|
470
|
-
(self.
|
|
473
|
+
(self.id, models.Span.events),
|
|
471
474
|
)
|
|
472
475
|
return [SpanEvent.from_dict(event) for event in value]
|
|
473
476
|
|
|
@@ -478,13 +481,13 @@ class Span(Node):
|
|
|
478
481
|
async def cumulative_token_count_total(
|
|
479
482
|
self,
|
|
480
483
|
info: Info[Context, None],
|
|
481
|
-
) -> Optional[
|
|
482
|
-
if self.
|
|
483
|
-
return self.
|
|
484
|
+
) -> Optional[float]:
|
|
485
|
+
if self.db_record:
|
|
486
|
+
return float(self.db_record.cumulative_llm_token_count_total)
|
|
484
487
|
value = await info.context.data_loaders.span_fields.load(
|
|
485
|
-
(self.
|
|
488
|
+
(self.id, models.Span.cumulative_llm_token_count_total),
|
|
486
489
|
)
|
|
487
|
-
return
|
|
490
|
+
return float(value) if value is not None else None
|
|
488
491
|
|
|
489
492
|
@strawberry.field(
|
|
490
493
|
description="Cumulative (prompt) token count from self and all descendant "
|
|
@@ -493,13 +496,13 @@ class Span(Node):
|
|
|
493
496
|
async def cumulative_token_count_prompt(
|
|
494
497
|
self,
|
|
495
498
|
info: Info[Context, None],
|
|
496
|
-
) -> Optional[
|
|
497
|
-
if self.
|
|
498
|
-
return self.
|
|
499
|
+
) -> Optional[float]:
|
|
500
|
+
if self.db_record:
|
|
501
|
+
return float(self.db_record.cumulative_llm_token_count_prompt)
|
|
499
502
|
value = await info.context.data_loaders.span_fields.load(
|
|
500
|
-
(self.
|
|
503
|
+
(self.id, models.Span.cumulative_llm_token_count_prompt),
|
|
501
504
|
)
|
|
502
|
-
return
|
|
505
|
+
return float(value) if value is not None else None
|
|
503
506
|
|
|
504
507
|
@strawberry.field(
|
|
505
508
|
description="Cumulative (completion) token count from self and all descendant "
|
|
@@ -508,13 +511,13 @@ class Span(Node):
|
|
|
508
511
|
async def cumulative_token_count_completion(
|
|
509
512
|
self,
|
|
510
513
|
info: Info[Context, None],
|
|
511
|
-
) -> Optional[
|
|
512
|
-
if self.
|
|
513
|
-
return self.
|
|
514
|
+
) -> Optional[float]:
|
|
515
|
+
if self.db_record:
|
|
516
|
+
return float(self.db_record.cumulative_llm_token_count_completion)
|
|
514
517
|
value = await info.context.data_loaders.span_fields.load(
|
|
515
|
-
(self.
|
|
518
|
+
(self.id, models.Span.cumulative_llm_token_count_completion),
|
|
516
519
|
)
|
|
517
|
-
return
|
|
520
|
+
return float(value) if value is not None else None
|
|
518
521
|
|
|
519
522
|
@strawberry.field(
|
|
520
523
|
description="Propagated status code that percolates up error status codes from "
|
|
@@ -524,27 +527,26 @@ class Span(Node):
|
|
|
524
527
|
self,
|
|
525
528
|
info: Info[Context, None],
|
|
526
529
|
) -> SpanStatusCode:
|
|
527
|
-
if self.
|
|
528
|
-
value = self.
|
|
530
|
+
if self.db_record:
|
|
531
|
+
value = self.db_record.cumulative_error_count
|
|
529
532
|
else:
|
|
530
533
|
value = await info.context.data_loaders.span_fields.load(
|
|
531
|
-
(self.
|
|
534
|
+
(self.id, models.Span.cumulative_error_count),
|
|
532
535
|
)
|
|
533
536
|
return SpanStatusCode.ERROR if value else SpanStatusCode.OK
|
|
534
537
|
|
|
535
538
|
@strawberry.field(
|
|
536
539
|
description=(
|
|
537
|
-
"Annotations associated with the span. This encompasses both "
|
|
538
|
-
"LLM and human annotations."
|
|
540
|
+
"Annotations associated with the span. This encompasses both LLM and human annotations."
|
|
539
541
|
)
|
|
540
542
|
) # type: ignore
|
|
541
543
|
async def span_annotations(
|
|
542
544
|
self,
|
|
543
545
|
info: Info[Context, None],
|
|
544
546
|
sort: Optional[SpanAnnotationSort] = UNSET,
|
|
545
|
-
filter: Optional[
|
|
547
|
+
filter: Optional[AnnotationFilter] = None,
|
|
546
548
|
) -> list[SpanAnnotation]:
|
|
547
|
-
span_id = self.
|
|
549
|
+
span_id = self.id
|
|
548
550
|
annotations = await info.context.data_loaders.span_annotations.load(span_id)
|
|
549
551
|
sort_key = SpanAnnotationColumn.name.value
|
|
550
552
|
sort_descending = False
|
|
@@ -558,24 +560,28 @@ class Span(Node):
|
|
|
558
560
|
annotations.sort(
|
|
559
561
|
key=lambda annotation: getattr(annotation, sort_key), reverse=sort_descending
|
|
560
562
|
)
|
|
561
|
-
return [
|
|
563
|
+
return [
|
|
564
|
+
SpanAnnotation(id=annotation.id, db_record=annotation) for annotation in annotations
|
|
565
|
+
]
|
|
562
566
|
|
|
563
567
|
@strawberry.field(description=("Notes associated with the span.")) # type: ignore
|
|
564
568
|
async def span_notes(
|
|
565
569
|
self,
|
|
566
570
|
info: Info[Context, None],
|
|
567
571
|
) -> list[SpanAnnotation]:
|
|
568
|
-
span_id = self.
|
|
572
|
+
span_id = self.id
|
|
569
573
|
annotations = await info.context.data_loaders.span_annotations.load(span_id)
|
|
570
574
|
annotations = [annotation for annotation in annotations if annotation.name == "note"]
|
|
571
575
|
annotations.sort(key=lambda annotation: getattr(annotation, "created_at"), reverse=False)
|
|
572
|
-
return [
|
|
576
|
+
return [
|
|
577
|
+
SpanAnnotation(id=annotation.id, db_record=annotation) for annotation in annotations
|
|
578
|
+
]
|
|
573
579
|
|
|
574
580
|
@strawberry.field(description="Summarizes each annotation (by name) associated with the span") # type: ignore
|
|
575
581
|
async def span_annotation_summaries(
|
|
576
582
|
self,
|
|
577
583
|
info: Info[Context, None],
|
|
578
|
-
filter: Optional[
|
|
584
|
+
filter: Optional[AnnotationFilter] = None,
|
|
579
585
|
) -> list[AnnotationSummary]:
|
|
580
586
|
"""
|
|
581
587
|
Retrieves and summarizes annotations associated with this span.
|
|
@@ -594,7 +600,7 @@ class Span(Node):
|
|
|
594
600
|
- data: A list of dictionaries with label statistics
|
|
595
601
|
"""
|
|
596
602
|
# Load all annotations for this span from the data loader
|
|
597
|
-
annotations = await info.context.data_loaders.span_annotations.load(self.
|
|
603
|
+
annotations = await info.context.data_loaders.span_annotations.load(self.id)
|
|
598
604
|
|
|
599
605
|
# Apply filter if provided to narrow down the annotations
|
|
600
606
|
if filter:
|
|
@@ -636,8 +642,11 @@ class Span(Node):
|
|
|
636
642
|
async def document_evaluations(
|
|
637
643
|
self,
|
|
638
644
|
info: Info[Context, None],
|
|
639
|
-
) -> list[
|
|
640
|
-
return
|
|
645
|
+
) -> list[DocumentAnnotation]:
|
|
646
|
+
return [
|
|
647
|
+
DocumentAnnotation(id=anno.id, db_record=anno)
|
|
648
|
+
for anno in await info.context.data_loaders.document_evaluations.load(self.id)
|
|
649
|
+
]
|
|
641
650
|
|
|
642
651
|
@strawberry.field(
|
|
643
652
|
description="Retrieval metrics: NDCG@K, Precision@K, Reciprocal Rank, etc.",
|
|
@@ -648,21 +657,21 @@ class Span(Node):
|
|
|
648
657
|
evaluation_name: Optional[str] = UNSET,
|
|
649
658
|
) -> list[DocumentRetrievalMetrics]:
|
|
650
659
|
num_documents = (
|
|
651
|
-
self.
|
|
652
|
-
if self.
|
|
660
|
+
self.db_record.num_documents
|
|
661
|
+
if self.db_record
|
|
653
662
|
else await info.context.data_loaders.span_fields.load(
|
|
654
|
-
(self.
|
|
663
|
+
(self.id, models.Span.num_documents),
|
|
655
664
|
)
|
|
656
665
|
)
|
|
657
666
|
if not num_documents:
|
|
658
667
|
return []
|
|
659
668
|
return await info.context.data_loaders.document_retrieval_metrics.load(
|
|
660
|
-
(self.
|
|
669
|
+
(self.id, evaluation_name or None, num_documents),
|
|
661
670
|
)
|
|
662
671
|
|
|
663
672
|
@strawberry.field
|
|
664
673
|
async def num_child_spans(self, info: Info[Context, None]) -> int:
|
|
665
|
-
return await info.context.data_loaders.num_child_spans.load(self.
|
|
674
|
+
return await info.context.data_loaders.num_child_spans.load(self.id)
|
|
666
675
|
|
|
667
676
|
@strawberry.field(
|
|
668
677
|
description="All descendant spans (children, grandchildren, etc.)",
|
|
@@ -691,9 +700,9 @@ class Span(Node):
|
|
|
691
700
|
before=before if isinstance(before, CursorString) else None,
|
|
692
701
|
)
|
|
693
702
|
span_rowids: Iterable[int] = await info.context.data_loaders.span_descendants.load(
|
|
694
|
-
(self.
|
|
703
|
+
(self.id, max_depth or None),
|
|
695
704
|
)
|
|
696
|
-
data = [Span(
|
|
705
|
+
data = [Span(id=span_rowid) for span_rowid in span_rowids]
|
|
697
706
|
return connection_from_list(data=data, args=args)
|
|
698
707
|
|
|
699
708
|
@strawberry.field(
|
|
@@ -704,9 +713,9 @@ class Span(Node):
|
|
|
704
713
|
info: Info[Context, None],
|
|
705
714
|
) -> SpanAsExampleRevision:
|
|
706
715
|
span = (
|
|
707
|
-
self.
|
|
708
|
-
if self.
|
|
709
|
-
else await info.context.data_loaders.span_by_id.load(self.
|
|
716
|
+
self.db_record
|
|
717
|
+
if self.db_record
|
|
718
|
+
else await info.context.data_loaders.span_by_id.load(self.id)
|
|
710
719
|
)
|
|
711
720
|
|
|
712
721
|
# Fetch annotations associated with this span
|
|
@@ -741,16 +750,16 @@ class Span(Node):
|
|
|
741
750
|
]: # use lazy types to avoid circular import: https://strawberry.rocks/docs/types/lazy
|
|
742
751
|
from phoenix.server.api.types.Project import Project
|
|
743
752
|
|
|
744
|
-
span_id = self.
|
|
753
|
+
span_id = self.id
|
|
745
754
|
project = await info.context.data_loaders.span_projects.load(span_id)
|
|
746
|
-
return Project(
|
|
755
|
+
return Project(id=project.id, db_record=project)
|
|
747
756
|
|
|
748
757
|
@strawberry.field(description="Indicates if the span is contained in any dataset") # type: ignore
|
|
749
758
|
async def contained_in_dataset(
|
|
750
759
|
self,
|
|
751
760
|
info: Info[Context, None],
|
|
752
761
|
) -> bool:
|
|
753
|
-
examples = await info.context.data_loaders.span_dataset_examples.load(self.
|
|
762
|
+
examples = await info.context.data_loaders.span_dataset_examples.load(self.id)
|
|
754
763
|
return bool(examples)
|
|
755
764
|
|
|
756
765
|
@strawberry.field(description="Invocation parameters for the span") # type: ignore
|
|
@@ -761,7 +770,7 @@ class Span(Node):
|
|
|
761
770
|
from phoenix.server.api.helpers.playground_clients import OpenAIStreamingClient
|
|
762
771
|
from phoenix.server.api.helpers.playground_registry import PLAYGROUND_CLIENT_REGISTRY
|
|
763
772
|
|
|
764
|
-
db_span: models.Span = await info.context.data_loaders.span_by_id.load(self.
|
|
773
|
+
db_span: models.Span = await info.context.data_loaders.span_by_id.load(self.id)
|
|
765
774
|
attributes = db_span.attributes
|
|
766
775
|
llm_provider = GenerativeProvider.get_model_provider_from_attributes(attributes)
|
|
767
776
|
if llm_provider is None:
|
|
@@ -790,6 +799,41 @@ class Span(Node):
|
|
|
790
799
|
)
|
|
791
800
|
]
|
|
792
801
|
|
|
802
|
+
@strawberry.field
|
|
803
|
+
async def cost_summary(self, info: Info[Context, None]) -> Optional[SpanCostSummary]:
|
|
804
|
+
span_cost = await info.context.data_loaders.span_cost_by_span.load(self.id)
|
|
805
|
+
if span_cost is None:
|
|
806
|
+
return None
|
|
807
|
+
return SpanCostSummary(
|
|
808
|
+
prompt=CostBreakdown(
|
|
809
|
+
tokens=span_cost.prompt_tokens,
|
|
810
|
+
cost=span_cost.prompt_cost,
|
|
811
|
+
),
|
|
812
|
+
completion=CostBreakdown(
|
|
813
|
+
tokens=span_cost.completion_tokens,
|
|
814
|
+
cost=span_cost.completion_cost,
|
|
815
|
+
),
|
|
816
|
+
total=CostBreakdown(
|
|
817
|
+
tokens=span_cost.total_tokens,
|
|
818
|
+
cost=span_cost.total_cost,
|
|
819
|
+
),
|
|
820
|
+
)
|
|
821
|
+
|
|
822
|
+
@strawberry.field
|
|
823
|
+
async def cost_detail_summary_entries(
|
|
824
|
+
self, info: Info[Context, None]
|
|
825
|
+
) -> list[SpanCostDetailSummaryEntry]:
|
|
826
|
+
loader = info.context.data_loaders.span_cost_detail_summary_entries_by_span
|
|
827
|
+
entries = await loader.load(self.id)
|
|
828
|
+
return [
|
|
829
|
+
SpanCostDetailSummaryEntry(
|
|
830
|
+
token_type=entry.token_type,
|
|
831
|
+
is_prompt=entry.is_prompt,
|
|
832
|
+
value=CostBreakdown(tokens=entry.value.tokens, cost=entry.value.cost),
|
|
833
|
+
)
|
|
834
|
+
for entry in entries
|
|
835
|
+
]
|
|
836
|
+
|
|
793
837
|
|
|
794
838
|
def _hide_embedding_vectors(attributes: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
795
839
|
if not (
|