arize-phoenix 11.23.1__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-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/METADATA +61 -36
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/RECORD +212 -162
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/WHEEL +1 -1
- {arize_phoenix-11.23.1.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 +2 -1
- phoenix/auth.py +27 -2
- phoenix/config.py +1594 -81
- phoenix/db/README.md +546 -28
- phoenix/db/bulk_inserter.py +119 -116
- phoenix/db/engines.py +140 -33
- phoenix/db/facilitator.py +22 -1
- phoenix/db/helpers.py +818 -65
- phoenix/db/iam_auth.py +64 -0
- phoenix/db/insertion/dataset.py +133 -1
- phoenix/db/insertion/document_annotation.py +9 -6
- phoenix/db/insertion/evaluation.py +2 -3
- phoenix/db/insertion/helpers.py +2 -2
- phoenix/db/insertion/session_annotation.py +176 -0
- phoenix/db/insertion/span_annotation.py +3 -4
- phoenix/db/insertion/trace_annotation.py +3 -4
- phoenix/db/insertion/types.py +41 -18
- 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/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 +364 -56
- phoenix/db/pg_config.py +10 -0
- phoenix/db/types/trace_retention.py +7 -6
- phoenix/experiments/functions.py +69 -19
- phoenix/inferences/inferences.py +1 -2
- phoenix/server/api/auth.py +9 -0
- phoenix/server/api/auth_messages.py +46 -0
- phoenix/server/api/context.py +60 -0
- phoenix/server/api/dataloaders/__init__.py +36 -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/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_summary_by_experiment_repeated_run_group.py +64 -0
- phoenix/server/api/dataloaders/span_cost_summary_by_project.py +28 -14
- phoenix/server/api/dataloaders/span_costs.py +3 -9
- 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/exceptions.py +5 -1
- phoenix/server/api/helpers/playground_clients.py +263 -83
- phoenix/server/api/helpers/playground_spans.py +2 -1
- phoenix/server/api/helpers/playground_users.py +26 -0
- phoenix/server/api/helpers/prompts/conversions/google.py +103 -0
- phoenix/server/api/helpers/prompts/models.py +61 -19
- phoenix/server/api/input_types/{SpanAnnotationFilter.py → AnnotationFilter.py} +22 -14
- phoenix/server/api/input_types/ChatCompletionInput.py +3 -0
- phoenix/server/api/input_types/CreateProjectSessionAnnotationInput.py +37 -0
- phoenix/server/api/input_types/DatasetFilter.py +5 -2
- phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
- phoenix/server/api/input_types/GenerativeModelInput.py +3 -0
- phoenix/server/api/input_types/ProjectSessionSort.py +158 -1
- phoenix/server/api/input_types/PromptVersionInput.py +47 -1
- phoenix/server/api/input_types/SpanSort.py +3 -2
- phoenix/server/api/input_types/UpdateAnnotationInput.py +34 -0
- phoenix/server/api/input_types/UserRoleInput.py +1 -0
- phoenix/server/api/mutations/__init__.py +8 -0
- phoenix/server/api/mutations/annotation_config_mutations.py +8 -8
- phoenix/server/api/mutations/api_key_mutations.py +15 -20
- phoenix/server/api/mutations/chat_mutations.py +106 -37
- 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 +11 -9
- phoenix/server/api/mutations/project_mutations.py +4 -4
- 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 +13 -8
- phoenix/server/api/mutations/trace_mutations.py +3 -3
- phoenix/server/api/mutations/user_mutations.py +55 -26
- phoenix/server/api/queries.py +501 -617
- phoenix/server/api/routers/__init__.py +2 -2
- phoenix/server/api/routers/auth.py +141 -87
- phoenix/server/api/routers/ldap.py +229 -0
- phoenix/server/api/routers/oauth2.py +349 -101
- phoenix/server/api/routers/v1/__init__.py +22 -4
- phoenix/server/api/routers/v1/annotation_configs.py +19 -30
- phoenix/server/api/routers/v1/annotations.py +455 -13
- phoenix/server/api/routers/v1/datasets.py +355 -68
- phoenix/server/api/routers/v1/documents.py +142 -0
- phoenix/server/api/routers/v1/evaluations.py +20 -28
- phoenix/server/api/routers/v1/experiment_evaluations.py +16 -6
- phoenix/server/api/routers/v1/experiment_runs.py +335 -59
- phoenix/server/api/routers/v1/experiments.py +475 -47
- phoenix/server/api/routers/v1/projects.py +16 -50
- phoenix/server/api/routers/v1/prompts.py +50 -39
- phoenix/server/api/routers/v1/sessions.py +108 -0
- phoenix/server/api/routers/v1/spans.py +156 -96
- phoenix/server/api/routers/v1/traces.py +51 -77
- phoenix/server/api/routers/v1/users.py +64 -24
- phoenix/server/api/routers/v1/utils.py +3 -7
- phoenix/server/api/subscriptions.py +257 -93
- 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/Dataset.py +199 -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 +215 -68
- phoenix/server/api/types/ExperimentComparison.py +3 -9
- phoenix/server/api/types/ExperimentRepeatedRunGroup.py +155 -0
- phoenix/server/api/types/ExperimentRepeatedRunGroupAnnotationSummary.py +9 -0
- phoenix/server/api/types/ExperimentRun.py +120 -70
- phoenix/server/api/types/ExperimentRunAnnotation.py +158 -39
- phoenix/server/api/types/GenerativeModel.py +95 -42
- phoenix/server/api/types/GenerativeProvider.py +1 -1
- phoenix/server/api/types/ModelInterface.py +7 -2
- phoenix/server/api/types/PlaygroundModel.py +12 -2
- phoenix/server/api/types/Project.py +218 -185
- phoenix/server/api/types/ProjectSession.py +146 -29
- 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/Span.py +130 -123
- phoenix/server/api/types/SpanAnnotation.py +189 -42
- phoenix/server/api/types/SystemApiKey.py +65 -1
- phoenix/server/api/types/Trace.py +184 -53
- phoenix/server/api/types/TraceAnnotation.py +149 -50
- phoenix/server/api/types/User.py +128 -33
- 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 +154 -36
- phoenix/server/authorization.py +5 -4
- phoenix/server/bearer_auth.py +13 -5
- phoenix/server/cost_tracking/cost_model_lookup.py +42 -14
- phoenix/server/cost_tracking/model_cost_manifest.json +1085 -194
- phoenix/server/daemons/generative_model_store.py +61 -9
- phoenix/server/daemons/span_cost_calculator.py +10 -8
- phoenix/server/dml_event.py +13 -0
- phoenix/server/email/sender.py +29 -2
- phoenix/server/grpc_server.py +9 -9
- phoenix/server/jwt_store.py +8 -6
- phoenix/server/ldap.py +1449 -0
- phoenix/server/main.py +9 -3
- phoenix/server/oauth2.py +330 -12
- phoenix/server/prometheus.py +43 -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 +51 -53
- phoenix/server/static/assets/components-BreFUQQa.js +6702 -0
- phoenix/server/static/assets/{index-BPCwGQr8.js → index-CTQoemZv.js} +42 -35
- 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-Bw30oz1A.js → vendor-recharts-V9cwpXsm.js} +7 -7
- phoenix/server/static/assets/{vendor-shiki-DZajAPeq.js → vendor-shiki-Do--csgv.js} +1 -1
- phoenix/server/static/assets/vendor-three-CmB8bl_y.js +3840 -0
- phoenix/server/templates/index.html +7 -1
- phoenix/server/thread_server.py +1 -2
- phoenix/server/utils.py +74 -0
- phoenix/session/client.py +55 -1
- phoenix/session/data_extractor.py +5 -0
- phoenix/session/evaluation.py +8 -4
- phoenix/session/session.py +44 -8
- phoenix/settings.py +2 -0
- phoenix/trace/attributes.py +80 -13
- phoenix/trace/dsl/query.py +2 -0
- phoenix/trace/projects.py +5 -0
- phoenix/utilities/template_formatters.py +1 -1
- phoenix/version.py +1 -1
- phoenix/server/api/types/Evaluation.py +0 -39
- phoenix/server/static/assets/components-D0DWAf0l.js +0 -5650
- phoenix/server/static/assets/pages-Creyamao.js +0 -8612
- phoenix/server/static/assets/vendor-CU36oj8y.js +0 -905
- phoenix/server/static/assets/vendor-CqDb5u4o.css +0 -1
- phoenix/server/static/assets/vendor-arizeai-Ctgw0e1G.js +0 -168
- phoenix/server/static/assets/vendor-codemirror-Cojjzqb9.js +0 -25
- phoenix/server/static/assets/vendor-three-BLWp5bic.js +0 -2998
- phoenix/utilities/deprecation.py +0 -31
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-11.23.1.dist-info → arize_phoenix-12.28.1.dist-info}/licenses/LICENSE +0 -0
phoenix/server/api/types/Span.py
CHANGED
|
@@ -23,25 +23,25 @@ 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
36
|
from phoenix.server.api.types.CostBreakdown import CostBreakdown
|
|
37
|
+
from phoenix.server.api.types.DocumentAnnotation import DocumentAnnotation
|
|
37
38
|
from phoenix.server.api.types.DocumentRetrievalMetrics import DocumentRetrievalMetrics
|
|
38
|
-
from phoenix.server.api.types.Evaluation import DocumentEvaluation
|
|
39
39
|
from phoenix.server.api.types.ExampleRevisionInterface import ExampleRevision
|
|
40
40
|
from phoenix.server.api.types.GenerativeProvider import GenerativeProvider
|
|
41
41
|
from phoenix.server.api.types.MimeType import MimeType
|
|
42
42
|
from phoenix.server.api.types.pagination import ConnectionArgs, CursorString, connection_from_list
|
|
43
43
|
from phoenix.server.api.types.SortDir import SortDir
|
|
44
|
-
from phoenix.server.api.types.SpanAnnotation import SpanAnnotation
|
|
44
|
+
from phoenix.server.api.types.SpanAnnotation import SpanAnnotation
|
|
45
45
|
from phoenix.server.api.types.SpanCostDetailSummaryEntry import SpanCostDetailSummaryEntry
|
|
46
46
|
from phoenix.server.api.types.SpanCostSummary import SpanCostSummary
|
|
47
47
|
from phoenix.server.api.types.SpanIOValue import SpanIOValue, truncate_value
|
|
@@ -123,11 +123,11 @@ SpanRowId: TypeAlias = int
|
|
|
123
123
|
|
|
124
124
|
@strawberry.type
|
|
125
125
|
class Span(Node):
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
id: NodeID[SpanRowId]
|
|
127
|
+
db_record: strawberry.Private[Optional[models.Span]] = None
|
|
128
128
|
|
|
129
129
|
def __post_init__(self) -> None:
|
|
130
|
-
if self.
|
|
130
|
+
if self.db_record and self.id != self.db_record.id:
|
|
131
131
|
raise ValueError("Span ID mismatch")
|
|
132
132
|
|
|
133
133
|
@strawberry.field
|
|
@@ -135,10 +135,10 @@ class Span(Node):
|
|
|
135
135
|
self,
|
|
136
136
|
info: Info[Context, None],
|
|
137
137
|
) -> str:
|
|
138
|
-
if self.
|
|
139
|
-
return self.
|
|
138
|
+
if self.db_record:
|
|
139
|
+
return self.db_record.name
|
|
140
140
|
value = await info.context.data_loaders.span_fields.load(
|
|
141
|
-
(self.
|
|
141
|
+
(self.id, models.Span.name),
|
|
142
142
|
)
|
|
143
143
|
return str(value)
|
|
144
144
|
|
|
@@ -147,11 +147,11 @@ class Span(Node):
|
|
|
147
147
|
self,
|
|
148
148
|
info: Info[Context, None],
|
|
149
149
|
) -> SpanStatusCode:
|
|
150
|
-
if self.
|
|
151
|
-
value = self.
|
|
150
|
+
if self.db_record:
|
|
151
|
+
value = self.db_record.status_code
|
|
152
152
|
else:
|
|
153
153
|
value = await info.context.data_loaders.span_fields.load(
|
|
154
|
-
(self.
|
|
154
|
+
(self.id, models.Span.status_code),
|
|
155
155
|
)
|
|
156
156
|
return SpanStatusCode(value)
|
|
157
157
|
|
|
@@ -160,10 +160,10 @@ class Span(Node):
|
|
|
160
160
|
self,
|
|
161
161
|
info: Info[Context, None],
|
|
162
162
|
) -> str:
|
|
163
|
-
if self.
|
|
164
|
-
return self.
|
|
163
|
+
if self.db_record:
|
|
164
|
+
return self.db_record.status_message
|
|
165
165
|
value = await info.context.data_loaders.span_fields.load(
|
|
166
|
-
(self.
|
|
166
|
+
(self.id, models.Span.status_message),
|
|
167
167
|
)
|
|
168
168
|
return str(value)
|
|
169
169
|
|
|
@@ -172,10 +172,10 @@ class Span(Node):
|
|
|
172
172
|
self,
|
|
173
173
|
info: Info[Context, None],
|
|
174
174
|
) -> datetime:
|
|
175
|
-
if self.
|
|
176
|
-
return self.
|
|
175
|
+
if self.db_record:
|
|
176
|
+
return self.db_record.start_time
|
|
177
177
|
value = await info.context.data_loaders.span_fields.load(
|
|
178
|
-
(self.
|
|
178
|
+
(self.id, models.Span.start_time),
|
|
179
179
|
)
|
|
180
180
|
return cast(datetime, value)
|
|
181
181
|
|
|
@@ -184,10 +184,10 @@ class Span(Node):
|
|
|
184
184
|
self,
|
|
185
185
|
info: Info[Context, None],
|
|
186
186
|
) -> Optional[datetime]:
|
|
187
|
-
if self.
|
|
188
|
-
return self.
|
|
187
|
+
if self.db_record:
|
|
188
|
+
return self.db_record.end_time
|
|
189
189
|
value = await info.context.data_loaders.span_fields.load(
|
|
190
|
-
(self.
|
|
190
|
+
(self.id, models.Span.end_time),
|
|
191
191
|
)
|
|
192
192
|
return cast(datetime, value)
|
|
193
193
|
|
|
@@ -196,10 +196,10 @@ class Span(Node):
|
|
|
196
196
|
self,
|
|
197
197
|
info: Info[Context, None],
|
|
198
198
|
) -> Optional[float]:
|
|
199
|
-
if self.
|
|
200
|
-
return self.
|
|
199
|
+
if self.db_record:
|
|
200
|
+
return self.db_record.latency_ms
|
|
201
201
|
value = await info.context.data_loaders.span_fields.load(
|
|
202
|
-
(self.
|
|
202
|
+
(self.id, models.Span.latency_ms),
|
|
203
203
|
)
|
|
204
204
|
return cast(float, value)
|
|
205
205
|
|
|
@@ -210,11 +210,11 @@ class Span(Node):
|
|
|
210
210
|
self,
|
|
211
211
|
info: Info[Context, None],
|
|
212
212
|
) -> Optional[ID]:
|
|
213
|
-
if self.
|
|
214
|
-
value = self.
|
|
213
|
+
if self.db_record:
|
|
214
|
+
value = self.db_record.parent_id
|
|
215
215
|
else:
|
|
216
216
|
value = await info.context.data_loaders.span_fields.load(
|
|
217
|
-
(self.
|
|
217
|
+
(self.id, models.Span.parent_id),
|
|
218
218
|
)
|
|
219
219
|
return None if value is None else ID(value)
|
|
220
220
|
|
|
@@ -223,11 +223,11 @@ class Span(Node):
|
|
|
223
223
|
self,
|
|
224
224
|
info: Info[Context, None],
|
|
225
225
|
) -> SpanKind:
|
|
226
|
-
if self.
|
|
227
|
-
value = self.
|
|
226
|
+
if self.db_record:
|
|
227
|
+
value = self.db_record.span_kind
|
|
228
228
|
else:
|
|
229
229
|
value = await info.context.data_loaders.span_fields.load(
|
|
230
|
-
(self.
|
|
230
|
+
(self.id, models.Span.span_kind),
|
|
231
231
|
)
|
|
232
232
|
return SpanKind(value)
|
|
233
233
|
|
|
@@ -236,11 +236,11 @@ class Span(Node):
|
|
|
236
236
|
self,
|
|
237
237
|
info: Info[Context, None],
|
|
238
238
|
) -> ID:
|
|
239
|
-
if self.
|
|
240
|
-
span_id = self.
|
|
239
|
+
if self.db_record:
|
|
240
|
+
span_id = self.db_record.span_id
|
|
241
241
|
else:
|
|
242
242
|
span_id = await info.context.data_loaders.span_fields.load(
|
|
243
|
-
(self.
|
|
243
|
+
(self.id, models.Span.span_id),
|
|
244
244
|
)
|
|
245
245
|
return ID(span_id)
|
|
246
246
|
|
|
@@ -249,31 +249,31 @@ class Span(Node):
|
|
|
249
249
|
self,
|
|
250
250
|
info: Info[Context, None],
|
|
251
251
|
) -> Annotated["Trace", strawberry.lazy(".Trace")]:
|
|
252
|
-
if self.
|
|
253
|
-
trace_rowid = self.
|
|
252
|
+
if self.db_record:
|
|
253
|
+
trace_rowid = self.db_record.trace_rowid
|
|
254
254
|
else:
|
|
255
255
|
trace_rowid = await info.context.data_loaders.span_fields.load(
|
|
256
|
-
(self.
|
|
256
|
+
(self.id, models.Span.trace_rowid),
|
|
257
257
|
)
|
|
258
258
|
from phoenix.server.api.types.Trace import Trace
|
|
259
259
|
|
|
260
|
-
return Trace(
|
|
260
|
+
return Trace(id=trace_rowid)
|
|
261
261
|
|
|
262
262
|
@strawberry.field
|
|
263
263
|
async def context(
|
|
264
264
|
self,
|
|
265
265
|
info: Info[Context, None],
|
|
266
266
|
) -> SpanContext:
|
|
267
|
-
if self.
|
|
268
|
-
trace_id = self.
|
|
269
|
-
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
|
|
270
270
|
else:
|
|
271
271
|
span_id, trace_id = await gather(
|
|
272
272
|
info.context.data_loaders.span_fields.load(
|
|
273
|
-
(self.
|
|
273
|
+
(self.id, models.Span.span_id),
|
|
274
274
|
),
|
|
275
275
|
info.context.data_loaders.span_fields.load(
|
|
276
|
-
(self.
|
|
276
|
+
(self.id, models.Trace.trace_id),
|
|
277
277
|
),
|
|
278
278
|
)
|
|
279
279
|
return SpanContext(trace_id=ID(trace_id), span_id=ID(span_id))
|
|
@@ -285,11 +285,11 @@ class Span(Node):
|
|
|
285
285
|
self,
|
|
286
286
|
info: Info[Context, None],
|
|
287
287
|
) -> str:
|
|
288
|
-
if self.
|
|
289
|
-
value = self.
|
|
288
|
+
if self.db_record:
|
|
289
|
+
value = self.db_record.attributes
|
|
290
290
|
else:
|
|
291
291
|
value = await info.context.data_loaders.span_fields.load(
|
|
292
|
-
(self.
|
|
292
|
+
(self.id, models.Span.attributes),
|
|
293
293
|
)
|
|
294
294
|
return json.dumps(_hide_embedding_vectors(value), cls=_JSONEncoder)
|
|
295
295
|
|
|
@@ -300,11 +300,11 @@ class Span(Node):
|
|
|
300
300
|
self,
|
|
301
301
|
info: Info[Context, None],
|
|
302
302
|
) -> Optional[str]:
|
|
303
|
-
if self.
|
|
304
|
-
value = self.
|
|
303
|
+
if self.db_record:
|
|
304
|
+
value = self.db_record.metadata_
|
|
305
305
|
else:
|
|
306
306
|
value = await info.context.data_loaders.span_fields.load(
|
|
307
|
-
(self.
|
|
307
|
+
(self.id, models.Span.metadata_),
|
|
308
308
|
)
|
|
309
309
|
return _convert_metadata_to_string(value)
|
|
310
310
|
|
|
@@ -313,10 +313,10 @@ class Span(Node):
|
|
|
313
313
|
self,
|
|
314
314
|
info: Info[Context, None],
|
|
315
315
|
) -> Optional[int]:
|
|
316
|
-
if self.
|
|
317
|
-
return self.
|
|
316
|
+
if self.db_record:
|
|
317
|
+
return self.db_record.num_documents
|
|
318
318
|
value = await info.context.data_loaders.span_fields.load(
|
|
319
|
-
(self.
|
|
319
|
+
(self.id, models.Span.num_documents),
|
|
320
320
|
)
|
|
321
321
|
return cast(int, value)
|
|
322
322
|
|
|
@@ -325,10 +325,10 @@ class Span(Node):
|
|
|
325
325
|
self,
|
|
326
326
|
info: Info[Context, None],
|
|
327
327
|
) -> Optional[int]:
|
|
328
|
-
if self.
|
|
329
|
-
return self.
|
|
328
|
+
if self.db_record:
|
|
329
|
+
return self.db_record.llm_token_count_total
|
|
330
330
|
value = await info.context.data_loaders.span_fields.load(
|
|
331
|
-
(self.
|
|
331
|
+
(self.id, models.Span.llm_token_count_total),
|
|
332
332
|
)
|
|
333
333
|
return cast(Optional[int], value)
|
|
334
334
|
|
|
@@ -337,10 +337,10 @@ class Span(Node):
|
|
|
337
337
|
self,
|
|
338
338
|
info: Info[Context, None],
|
|
339
339
|
) -> Optional[int]:
|
|
340
|
-
if self.
|
|
341
|
-
return self.
|
|
340
|
+
if self.db_record:
|
|
341
|
+
return self.db_record.llm_token_count_prompt
|
|
342
342
|
value = await info.context.data_loaders.span_fields.load(
|
|
343
|
-
(self.
|
|
343
|
+
(self.id, models.Span.llm_token_count_prompt),
|
|
344
344
|
)
|
|
345
345
|
return cast(Optional[int], value)
|
|
346
346
|
|
|
@@ -349,10 +349,10 @@ class Span(Node):
|
|
|
349
349
|
self,
|
|
350
350
|
info: Info[Context, None],
|
|
351
351
|
) -> Optional[int]:
|
|
352
|
-
if self.
|
|
353
|
-
return self.
|
|
352
|
+
if self.db_record:
|
|
353
|
+
return self.db_record.llm_token_count_completion
|
|
354
354
|
value = await info.context.data_loaders.span_fields.load(
|
|
355
|
-
(self.
|
|
355
|
+
(self.id, models.Span.llm_token_count_completion),
|
|
356
356
|
)
|
|
357
357
|
return cast(Optional[int], value)
|
|
358
358
|
|
|
@@ -361,11 +361,11 @@ class Span(Node):
|
|
|
361
361
|
self,
|
|
362
362
|
info: Info[Context, None],
|
|
363
363
|
) -> TokenCountPromptDetails:
|
|
364
|
-
if self.
|
|
365
|
-
attributes = self.
|
|
364
|
+
if self.db_record:
|
|
365
|
+
attributes = self.db_record.attributes
|
|
366
366
|
else:
|
|
367
367
|
attributes = await info.context.data_loaders.span_fields.load(
|
|
368
|
-
(self.
|
|
368
|
+
(self.id, models.Span.attributes),
|
|
369
369
|
)
|
|
370
370
|
|
|
371
371
|
cache_read: Optional[int] = None
|
|
@@ -403,28 +403,28 @@ class Span(Node):
|
|
|
403
403
|
self,
|
|
404
404
|
info: Info[Context, None],
|
|
405
405
|
) -> Optional[SpanIOValue]:
|
|
406
|
-
if self.
|
|
407
|
-
input_value = self.
|
|
406
|
+
if self.db_record:
|
|
407
|
+
input_value = self.db_record.input_value
|
|
408
408
|
if input_value is None or input_value == "":
|
|
409
409
|
return None
|
|
410
410
|
input_value = str(input_value)
|
|
411
|
-
mime_type = self.
|
|
411
|
+
mime_type = self.db_record.input_mime_type
|
|
412
412
|
return SpanIOValue(
|
|
413
413
|
cached_value=input_value,
|
|
414
414
|
mime_type=MimeType(mime_type),
|
|
415
415
|
)
|
|
416
416
|
mime_type, input_value_first_101_chars = await gather(
|
|
417
417
|
info.context.data_loaders.span_fields.load(
|
|
418
|
-
(self.
|
|
418
|
+
(self.id, models.Span.input_mime_type),
|
|
419
419
|
),
|
|
420
420
|
info.context.data_loaders.span_fields.load(
|
|
421
|
-
(self.
|
|
421
|
+
(self.id, models.Span.input_value_first_101_chars),
|
|
422
422
|
),
|
|
423
423
|
)
|
|
424
424
|
if not input_value_first_101_chars:
|
|
425
425
|
return None
|
|
426
426
|
return SpanIOValue(
|
|
427
|
-
span_rowid=self.
|
|
427
|
+
span_rowid=self.id,
|
|
428
428
|
attr=models.Span.input_value,
|
|
429
429
|
truncated_value=truncate_value(input_value_first_101_chars),
|
|
430
430
|
mime_type=MimeType(mime_type),
|
|
@@ -435,28 +435,28 @@ class Span(Node):
|
|
|
435
435
|
self,
|
|
436
436
|
info: Info[Context, None],
|
|
437
437
|
) -> Optional[SpanIOValue]:
|
|
438
|
-
if self.
|
|
439
|
-
output_value = self.
|
|
438
|
+
if self.db_record:
|
|
439
|
+
output_value = self.db_record.output_value
|
|
440
440
|
if output_value is None or output_value == "":
|
|
441
441
|
return None
|
|
442
442
|
output_value = str(output_value)
|
|
443
|
-
mime_type = self.
|
|
443
|
+
mime_type = self.db_record.output_mime_type
|
|
444
444
|
return SpanIOValue(
|
|
445
445
|
cached_value=output_value,
|
|
446
446
|
mime_type=MimeType(mime_type),
|
|
447
447
|
)
|
|
448
448
|
mime_type, output_value_first_101_chars = await gather(
|
|
449
449
|
info.context.data_loaders.span_fields.load(
|
|
450
|
-
(self.
|
|
450
|
+
(self.id, models.Span.output_mime_type),
|
|
451
451
|
),
|
|
452
452
|
info.context.data_loaders.span_fields.load(
|
|
453
|
-
(self.
|
|
453
|
+
(self.id, models.Span.output_value_first_101_chars),
|
|
454
454
|
),
|
|
455
455
|
)
|
|
456
456
|
if not output_value_first_101_chars:
|
|
457
457
|
return None
|
|
458
458
|
return SpanIOValue(
|
|
459
|
-
span_rowid=self.
|
|
459
|
+
span_rowid=self.id,
|
|
460
460
|
attr=models.Span.output_value,
|
|
461
461
|
truncated_value=truncate_value(output_value_first_101_chars),
|
|
462
462
|
mime_type=MimeType(mime_type),
|
|
@@ -467,10 +467,10 @@ class Span(Node):
|
|
|
467
467
|
self,
|
|
468
468
|
info: Info[Context, None],
|
|
469
469
|
) -> list[SpanEvent]:
|
|
470
|
-
if self.
|
|
471
|
-
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]
|
|
472
472
|
value = await info.context.data_loaders.span_fields.load(
|
|
473
|
-
(self.
|
|
473
|
+
(self.id, models.Span.events),
|
|
474
474
|
)
|
|
475
475
|
return [SpanEvent.from_dict(event) for event in value]
|
|
476
476
|
|
|
@@ -481,13 +481,13 @@ class Span(Node):
|
|
|
481
481
|
async def cumulative_token_count_total(
|
|
482
482
|
self,
|
|
483
483
|
info: Info[Context, None],
|
|
484
|
-
) -> Optional[
|
|
485
|
-
if self.
|
|
486
|
-
return self.
|
|
484
|
+
) -> Optional[float]:
|
|
485
|
+
if self.db_record:
|
|
486
|
+
return float(self.db_record.cumulative_llm_token_count_total)
|
|
487
487
|
value = await info.context.data_loaders.span_fields.load(
|
|
488
|
-
(self.
|
|
488
|
+
(self.id, models.Span.cumulative_llm_token_count_total),
|
|
489
489
|
)
|
|
490
|
-
return
|
|
490
|
+
return float(value) if value is not None else None
|
|
491
491
|
|
|
492
492
|
@strawberry.field(
|
|
493
493
|
description="Cumulative (prompt) token count from self and all descendant "
|
|
@@ -496,13 +496,13 @@ class Span(Node):
|
|
|
496
496
|
async def cumulative_token_count_prompt(
|
|
497
497
|
self,
|
|
498
498
|
info: Info[Context, None],
|
|
499
|
-
) -> Optional[
|
|
500
|
-
if self.
|
|
501
|
-
return self.
|
|
499
|
+
) -> Optional[float]:
|
|
500
|
+
if self.db_record:
|
|
501
|
+
return float(self.db_record.cumulative_llm_token_count_prompt)
|
|
502
502
|
value = await info.context.data_loaders.span_fields.load(
|
|
503
|
-
(self.
|
|
503
|
+
(self.id, models.Span.cumulative_llm_token_count_prompt),
|
|
504
504
|
)
|
|
505
|
-
return
|
|
505
|
+
return float(value) if value is not None else None
|
|
506
506
|
|
|
507
507
|
@strawberry.field(
|
|
508
508
|
description="Cumulative (completion) token count from self and all descendant "
|
|
@@ -511,13 +511,13 @@ class Span(Node):
|
|
|
511
511
|
async def cumulative_token_count_completion(
|
|
512
512
|
self,
|
|
513
513
|
info: Info[Context, None],
|
|
514
|
-
) -> Optional[
|
|
515
|
-
if self.
|
|
516
|
-
return self.
|
|
514
|
+
) -> Optional[float]:
|
|
515
|
+
if self.db_record:
|
|
516
|
+
return float(self.db_record.cumulative_llm_token_count_completion)
|
|
517
517
|
value = await info.context.data_loaders.span_fields.load(
|
|
518
|
-
(self.
|
|
518
|
+
(self.id, models.Span.cumulative_llm_token_count_completion),
|
|
519
519
|
)
|
|
520
|
-
return
|
|
520
|
+
return float(value) if value is not None else None
|
|
521
521
|
|
|
522
522
|
@strawberry.field(
|
|
523
523
|
description="Propagated status code that percolates up error status codes from "
|
|
@@ -527,11 +527,11 @@ class Span(Node):
|
|
|
527
527
|
self,
|
|
528
528
|
info: Info[Context, None],
|
|
529
529
|
) -> SpanStatusCode:
|
|
530
|
-
if self.
|
|
531
|
-
value = self.
|
|
530
|
+
if self.db_record:
|
|
531
|
+
value = self.db_record.cumulative_error_count
|
|
532
532
|
else:
|
|
533
533
|
value = await info.context.data_loaders.span_fields.load(
|
|
534
|
-
(self.
|
|
534
|
+
(self.id, models.Span.cumulative_error_count),
|
|
535
535
|
)
|
|
536
536
|
return SpanStatusCode.ERROR if value else SpanStatusCode.OK
|
|
537
537
|
|
|
@@ -544,9 +544,9 @@ class Span(Node):
|
|
|
544
544
|
self,
|
|
545
545
|
info: Info[Context, None],
|
|
546
546
|
sort: Optional[SpanAnnotationSort] = UNSET,
|
|
547
|
-
filter: Optional[
|
|
547
|
+
filter: Optional[AnnotationFilter] = None,
|
|
548
548
|
) -> list[SpanAnnotation]:
|
|
549
|
-
span_id = self.
|
|
549
|
+
span_id = self.id
|
|
550
550
|
annotations = await info.context.data_loaders.span_annotations.load(span_id)
|
|
551
551
|
sort_key = SpanAnnotationColumn.name.value
|
|
552
552
|
sort_descending = False
|
|
@@ -560,24 +560,28 @@ class Span(Node):
|
|
|
560
560
|
annotations.sort(
|
|
561
561
|
key=lambda annotation: getattr(annotation, sort_key), reverse=sort_descending
|
|
562
562
|
)
|
|
563
|
-
return [
|
|
563
|
+
return [
|
|
564
|
+
SpanAnnotation(id=annotation.id, db_record=annotation) for annotation in annotations
|
|
565
|
+
]
|
|
564
566
|
|
|
565
567
|
@strawberry.field(description=("Notes associated with the span.")) # type: ignore
|
|
566
568
|
async def span_notes(
|
|
567
569
|
self,
|
|
568
570
|
info: Info[Context, None],
|
|
569
571
|
) -> list[SpanAnnotation]:
|
|
570
|
-
span_id = self.
|
|
572
|
+
span_id = self.id
|
|
571
573
|
annotations = await info.context.data_loaders.span_annotations.load(span_id)
|
|
572
574
|
annotations = [annotation for annotation in annotations if annotation.name == "note"]
|
|
573
575
|
annotations.sort(key=lambda annotation: getattr(annotation, "created_at"), reverse=False)
|
|
574
|
-
return [
|
|
576
|
+
return [
|
|
577
|
+
SpanAnnotation(id=annotation.id, db_record=annotation) for annotation in annotations
|
|
578
|
+
]
|
|
575
579
|
|
|
576
580
|
@strawberry.field(description="Summarizes each annotation (by name) associated with the span") # type: ignore
|
|
577
581
|
async def span_annotation_summaries(
|
|
578
582
|
self,
|
|
579
583
|
info: Info[Context, None],
|
|
580
|
-
filter: Optional[
|
|
584
|
+
filter: Optional[AnnotationFilter] = None,
|
|
581
585
|
) -> list[AnnotationSummary]:
|
|
582
586
|
"""
|
|
583
587
|
Retrieves and summarizes annotations associated with this span.
|
|
@@ -596,7 +600,7 @@ class Span(Node):
|
|
|
596
600
|
- data: A list of dictionaries with label statistics
|
|
597
601
|
"""
|
|
598
602
|
# Load all annotations for this span from the data loader
|
|
599
|
-
annotations = await info.context.data_loaders.span_annotations.load(self.
|
|
603
|
+
annotations = await info.context.data_loaders.span_annotations.load(self.id)
|
|
600
604
|
|
|
601
605
|
# Apply filter if provided to narrow down the annotations
|
|
602
606
|
if filter:
|
|
@@ -638,8 +642,11 @@ class Span(Node):
|
|
|
638
642
|
async def document_evaluations(
|
|
639
643
|
self,
|
|
640
644
|
info: Info[Context, None],
|
|
641
|
-
) -> list[
|
|
642
|
-
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
|
+
]
|
|
643
650
|
|
|
644
651
|
@strawberry.field(
|
|
645
652
|
description="Retrieval metrics: NDCG@K, Precision@K, Reciprocal Rank, etc.",
|
|
@@ -650,21 +657,21 @@ class Span(Node):
|
|
|
650
657
|
evaluation_name: Optional[str] = UNSET,
|
|
651
658
|
) -> list[DocumentRetrievalMetrics]:
|
|
652
659
|
num_documents = (
|
|
653
|
-
self.
|
|
654
|
-
if self.
|
|
660
|
+
self.db_record.num_documents
|
|
661
|
+
if self.db_record
|
|
655
662
|
else await info.context.data_loaders.span_fields.load(
|
|
656
|
-
(self.
|
|
663
|
+
(self.id, models.Span.num_documents),
|
|
657
664
|
)
|
|
658
665
|
)
|
|
659
666
|
if not num_documents:
|
|
660
667
|
return []
|
|
661
668
|
return await info.context.data_loaders.document_retrieval_metrics.load(
|
|
662
|
-
(self.
|
|
669
|
+
(self.id, evaluation_name or None, num_documents),
|
|
663
670
|
)
|
|
664
671
|
|
|
665
672
|
@strawberry.field
|
|
666
673
|
async def num_child_spans(self, info: Info[Context, None]) -> int:
|
|
667
|
-
return await info.context.data_loaders.num_child_spans.load(self.
|
|
674
|
+
return await info.context.data_loaders.num_child_spans.load(self.id)
|
|
668
675
|
|
|
669
676
|
@strawberry.field(
|
|
670
677
|
description="All descendant spans (children, grandchildren, etc.)",
|
|
@@ -693,9 +700,9 @@ class Span(Node):
|
|
|
693
700
|
before=before if isinstance(before, CursorString) else None,
|
|
694
701
|
)
|
|
695
702
|
span_rowids: Iterable[int] = await info.context.data_loaders.span_descendants.load(
|
|
696
|
-
(self.
|
|
703
|
+
(self.id, max_depth or None),
|
|
697
704
|
)
|
|
698
|
-
data = [Span(
|
|
705
|
+
data = [Span(id=span_rowid) for span_rowid in span_rowids]
|
|
699
706
|
return connection_from_list(data=data, args=args)
|
|
700
707
|
|
|
701
708
|
@strawberry.field(
|
|
@@ -706,9 +713,9 @@ class Span(Node):
|
|
|
706
713
|
info: Info[Context, None],
|
|
707
714
|
) -> SpanAsExampleRevision:
|
|
708
715
|
span = (
|
|
709
|
-
self.
|
|
710
|
-
if self.
|
|
711
|
-
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)
|
|
712
719
|
)
|
|
713
720
|
|
|
714
721
|
# Fetch annotations associated with this span
|
|
@@ -743,16 +750,16 @@ class Span(Node):
|
|
|
743
750
|
]: # use lazy types to avoid circular import: https://strawberry.rocks/docs/types/lazy
|
|
744
751
|
from phoenix.server.api.types.Project import Project
|
|
745
752
|
|
|
746
|
-
span_id = self.
|
|
753
|
+
span_id = self.id
|
|
747
754
|
project = await info.context.data_loaders.span_projects.load(span_id)
|
|
748
|
-
return Project(
|
|
755
|
+
return Project(id=project.id, db_record=project)
|
|
749
756
|
|
|
750
757
|
@strawberry.field(description="Indicates if the span is contained in any dataset") # type: ignore
|
|
751
758
|
async def contained_in_dataset(
|
|
752
759
|
self,
|
|
753
760
|
info: Info[Context, None],
|
|
754
761
|
) -> bool:
|
|
755
|
-
examples = await info.context.data_loaders.span_dataset_examples.load(self.
|
|
762
|
+
examples = await info.context.data_loaders.span_dataset_examples.load(self.id)
|
|
756
763
|
return bool(examples)
|
|
757
764
|
|
|
758
765
|
@strawberry.field(description="Invocation parameters for the span") # type: ignore
|
|
@@ -763,7 +770,7 @@ class Span(Node):
|
|
|
763
770
|
from phoenix.server.api.helpers.playground_clients import OpenAIStreamingClient
|
|
764
771
|
from phoenix.server.api.helpers.playground_registry import PLAYGROUND_CLIENT_REGISTRY
|
|
765
772
|
|
|
766
|
-
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)
|
|
767
774
|
attributes = db_span.attributes
|
|
768
775
|
llm_provider = GenerativeProvider.get_model_provider_from_attributes(attributes)
|
|
769
776
|
if llm_provider is None:
|
|
@@ -794,7 +801,7 @@ class Span(Node):
|
|
|
794
801
|
|
|
795
802
|
@strawberry.field
|
|
796
803
|
async def cost_summary(self, info: Info[Context, None]) -> Optional[SpanCostSummary]:
|
|
797
|
-
span_cost = await info.context.data_loaders.span_cost_by_span.load(self.
|
|
804
|
+
span_cost = await info.context.data_loaders.span_cost_by_span.load(self.id)
|
|
798
805
|
if span_cost is None:
|
|
799
806
|
return None
|
|
800
807
|
return SpanCostSummary(
|
|
@@ -817,7 +824,7 @@ class Span(Node):
|
|
|
817
824
|
self, info: Info[Context, None]
|
|
818
825
|
) -> list[SpanCostDetailSummaryEntry]:
|
|
819
826
|
loader = info.context.data_loaders.span_cost_detail_summary_entries_by_span
|
|
820
|
-
entries = await loader.load(self.
|
|
827
|
+
entries = await loader.load(self.id)
|
|
821
828
|
return [
|
|
822
829
|
SpanCostDetailSummaryEntry(
|
|
823
830
|
token_type=entry.token_type,
|