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
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from math import isfinite
|
|
3
|
+
from typing import TYPE_CHECKING, Annotated, Optional
|
|
2
4
|
|
|
3
5
|
import strawberry
|
|
4
|
-
from strawberry import Private
|
|
5
6
|
from strawberry.relay import GlobalID, Node, NodeID
|
|
6
7
|
from strawberry.scalars import JSON
|
|
7
8
|
from strawberry.types import Info
|
|
@@ -12,56 +13,202 @@ from phoenix.server.api.context import Context
|
|
|
12
13
|
from .Annotation import Annotation
|
|
13
14
|
from .AnnotationSource import AnnotationSource
|
|
14
15
|
from .AnnotatorKind import AnnotatorKind
|
|
15
|
-
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .Span import Span
|
|
19
|
+
from .User import User
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
@strawberry.type
|
|
19
23
|
class SpanAnnotation(Node, Annotation):
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
id: NodeID[int]
|
|
25
|
+
db_record: strawberry.Private[Optional[models.SpanAnnotation]] = None
|
|
26
|
+
|
|
27
|
+
def __post_init__(self) -> None:
|
|
28
|
+
if self.db_record and self.id != self.db_record.id:
|
|
29
|
+
raise ValueError("SpanAnnotation ID mismatch")
|
|
30
|
+
|
|
31
|
+
@strawberry.field(description="Name of the annotation, e.g. 'helpfulness' or 'relevance'.") # type: ignore
|
|
32
|
+
async def name(
|
|
33
|
+
self,
|
|
34
|
+
info: Info[Context, None],
|
|
35
|
+
) -> str:
|
|
36
|
+
if self.db_record:
|
|
37
|
+
val = self.db_record.name
|
|
38
|
+
else:
|
|
39
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
40
|
+
(self.id, models.SpanAnnotation.name),
|
|
41
|
+
)
|
|
42
|
+
return val
|
|
43
|
+
|
|
44
|
+
@strawberry.field(description="The kind of annotator that produced the annotation.") # type: ignore
|
|
45
|
+
async def annotator_kind(
|
|
46
|
+
self,
|
|
47
|
+
info: Info[Context, None],
|
|
48
|
+
) -> AnnotatorKind:
|
|
49
|
+
if self.db_record:
|
|
50
|
+
val = self.db_record.annotator_kind
|
|
51
|
+
else:
|
|
52
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
53
|
+
(self.id, models.SpanAnnotation.annotator_kind),
|
|
54
|
+
)
|
|
55
|
+
return AnnotatorKind(val)
|
|
56
|
+
|
|
57
|
+
@strawberry.field(
|
|
58
|
+
description="Value of the annotation in the form of a string, e.g. "
|
|
59
|
+
"'helpful' or 'not helpful'. Note that the label is not necessarily binary."
|
|
60
|
+
) # type: ignore
|
|
61
|
+
async def label(
|
|
62
|
+
self,
|
|
63
|
+
info: Info[Context, None],
|
|
64
|
+
) -> Optional[str]:
|
|
65
|
+
if self.db_record:
|
|
66
|
+
val = self.db_record.label
|
|
67
|
+
else:
|
|
68
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
69
|
+
(self.id, models.SpanAnnotation.label),
|
|
70
|
+
)
|
|
71
|
+
return val
|
|
72
|
+
|
|
73
|
+
@strawberry.field(
|
|
74
|
+
description="Value of the annotation in the form of a numeric score.",
|
|
75
|
+
) # type: ignore
|
|
76
|
+
async def score(
|
|
77
|
+
self,
|
|
78
|
+
info: Info[Context, None],
|
|
79
|
+
) -> Optional[float]:
|
|
80
|
+
if self.db_record:
|
|
81
|
+
val = self.db_record.score
|
|
82
|
+
else:
|
|
83
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
84
|
+
(self.id, models.SpanAnnotation.score),
|
|
85
|
+
)
|
|
86
|
+
return val if val is not None and isfinite(val) else None
|
|
87
|
+
|
|
88
|
+
@strawberry.field(
|
|
89
|
+
description="The annotator's explanation for the annotation result (i.e. "
|
|
90
|
+
"score or label, or both) given to the subject."
|
|
91
|
+
) # type: ignore
|
|
92
|
+
async def explanation(
|
|
93
|
+
self,
|
|
94
|
+
info: Info[Context, None],
|
|
95
|
+
) -> Optional[str]:
|
|
96
|
+
if self.db_record:
|
|
97
|
+
val = self.db_record.explanation
|
|
98
|
+
else:
|
|
99
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
100
|
+
(self.id, models.SpanAnnotation.explanation),
|
|
101
|
+
)
|
|
102
|
+
return val
|
|
103
|
+
|
|
104
|
+
@strawberry.field(description="Metadata about the annotation.") # type: ignore
|
|
105
|
+
async def metadata(
|
|
106
|
+
self,
|
|
107
|
+
info: Info[Context, None],
|
|
108
|
+
) -> JSON:
|
|
109
|
+
if self.db_record:
|
|
110
|
+
val = self.db_record.metadata_
|
|
111
|
+
else:
|
|
112
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
113
|
+
(self.id, models.SpanAnnotation.metadata_),
|
|
114
|
+
)
|
|
115
|
+
return val
|
|
116
|
+
|
|
117
|
+
@strawberry.field(description="The source of the annotation.") # type: ignore
|
|
118
|
+
async def source(
|
|
119
|
+
self,
|
|
120
|
+
info: Info[Context, None],
|
|
121
|
+
) -> AnnotationSource:
|
|
122
|
+
if self.db_record:
|
|
123
|
+
val = self.db_record.source
|
|
124
|
+
else:
|
|
125
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
126
|
+
(self.id, models.SpanAnnotation.source),
|
|
127
|
+
)
|
|
128
|
+
return AnnotationSource(val)
|
|
129
|
+
|
|
130
|
+
@strawberry.field(description="The identifier of the annotation.") # type: ignore
|
|
131
|
+
async def identifier(
|
|
132
|
+
self,
|
|
133
|
+
info: Info[Context, None],
|
|
134
|
+
) -> str:
|
|
135
|
+
if self.db_record:
|
|
136
|
+
val = self.db_record.identifier
|
|
137
|
+
else:
|
|
138
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
139
|
+
(self.id, models.SpanAnnotation.identifier),
|
|
140
|
+
)
|
|
141
|
+
return val
|
|
142
|
+
|
|
143
|
+
@strawberry.field(description="The date and time when the annotation was created.") # type: ignore
|
|
144
|
+
async def created_at(
|
|
145
|
+
self,
|
|
146
|
+
info: Info[Context, None],
|
|
147
|
+
) -> datetime:
|
|
148
|
+
if self.db_record:
|
|
149
|
+
val = self.db_record.created_at
|
|
150
|
+
else:
|
|
151
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
152
|
+
(self.id, models.SpanAnnotation.created_at),
|
|
153
|
+
)
|
|
154
|
+
return val
|
|
155
|
+
|
|
156
|
+
@strawberry.field(description="The date and time when the annotation was last updated.") # type: ignore
|
|
157
|
+
async def updated_at(
|
|
158
|
+
self,
|
|
159
|
+
info: Info[Context, None],
|
|
160
|
+
) -> datetime:
|
|
161
|
+
if self.db_record:
|
|
162
|
+
val = self.db_record.updated_at
|
|
163
|
+
else:
|
|
164
|
+
val = await info.context.data_loaders.span_annotation_fields.load(
|
|
165
|
+
(self.id, models.SpanAnnotation.updated_at),
|
|
166
|
+
)
|
|
167
|
+
return val
|
|
27
168
|
|
|
28
169
|
@strawberry.field
|
|
29
|
-
async def span_id(
|
|
170
|
+
async def span_id(
|
|
171
|
+
self,
|
|
172
|
+
info: Info[Context, None],
|
|
173
|
+
) -> GlobalID:
|
|
30
174
|
from phoenix.server.api.types.Span import Span
|
|
31
175
|
|
|
32
|
-
|
|
176
|
+
if self.db_record:
|
|
177
|
+
span_rowid = self.db_record.span_rowid
|
|
178
|
+
else:
|
|
179
|
+
span_rowid = await info.context.data_loaders.span_annotation_fields.load(
|
|
180
|
+
(self.id, models.SpanAnnotation.span_rowid),
|
|
181
|
+
)
|
|
182
|
+
return GlobalID(type_name=Span.__name__, node_id=str(span_rowid))
|
|
33
183
|
|
|
34
|
-
@strawberry.field
|
|
184
|
+
@strawberry.field(description="The span associated with the annotation.") # type: ignore
|
|
185
|
+
async def span(
|
|
186
|
+
self,
|
|
187
|
+
info: Info[Context, None],
|
|
188
|
+
) -> Annotated["Span", strawberry.lazy(".Span")]:
|
|
189
|
+
if self.db_record:
|
|
190
|
+
span_rowid = self.db_record.span_rowid
|
|
191
|
+
else:
|
|
192
|
+
span_rowid = await info.context.data_loaders.span_annotation_fields.load(
|
|
193
|
+
(self.id, models.SpanAnnotation.span_rowid),
|
|
194
|
+
)
|
|
195
|
+
from .Span import Span
|
|
196
|
+
|
|
197
|
+
return Span(id=span_rowid)
|
|
198
|
+
|
|
199
|
+
@strawberry.field(description="The user that produced the annotation.") # type: ignore
|
|
35
200
|
async def user(
|
|
36
201
|
self,
|
|
37
202
|
info: Info[Context, None],
|
|
38
|
-
) -> Optional[User]:
|
|
39
|
-
if self.
|
|
203
|
+
) -> Optional[Annotated["User", strawberry.lazy(".User")]]:
|
|
204
|
+
if self.db_record:
|
|
205
|
+
user_id = self.db_record.user_id
|
|
206
|
+
else:
|
|
207
|
+
user_id = await info.context.data_loaders.span_annotation_fields.load(
|
|
208
|
+
(self.id, models.SpanAnnotation.user_id),
|
|
209
|
+
)
|
|
210
|
+
if user_id is None:
|
|
40
211
|
return None
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return to_gql_user(user)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def to_gql_span_annotation(
|
|
48
|
-
annotation: models.SpanAnnotation,
|
|
49
|
-
) -> SpanAnnotation:
|
|
50
|
-
"""
|
|
51
|
-
Converts an ORM span annotation to a GraphQL SpanAnnotation.
|
|
52
|
-
"""
|
|
53
|
-
return SpanAnnotation(
|
|
54
|
-
id_attr=annotation.id,
|
|
55
|
-
user_id=annotation.user_id,
|
|
56
|
-
span_rowid=annotation.span_rowid,
|
|
57
|
-
name=annotation.name,
|
|
58
|
-
annotator_kind=AnnotatorKind(annotation.annotator_kind),
|
|
59
|
-
label=annotation.label,
|
|
60
|
-
score=annotation.score,
|
|
61
|
-
explanation=annotation.explanation,
|
|
62
|
-
metadata=annotation.metadata_,
|
|
63
|
-
source=AnnotationSource(annotation.source),
|
|
64
|
-
identifier=annotation.identifier,
|
|
65
|
-
created_at=annotation.created_at,
|
|
66
|
-
updated_at=annotation.updated_at,
|
|
67
|
-
)
|
|
212
|
+
from .User import User
|
|
213
|
+
|
|
214
|
+
return User(id=user_id)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import strawberry
|
|
2
|
+
|
|
3
|
+
from phoenix.server.api.types.CostBreakdown import CostBreakdown
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@strawberry.type
|
|
7
|
+
class SpanCostSummary:
|
|
8
|
+
prompt: CostBreakdown = strawberry.field(default_factory=CostBreakdown)
|
|
9
|
+
completion: CostBreakdown = strawberry.field(default_factory=CostBreakdown)
|
|
10
|
+
total: CostBreakdown = strawberry.field(default_factory=CostBreakdown)
|
|
@@ -1,9 +1,73 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
1
4
|
import strawberry
|
|
2
5
|
from strawberry.relay import Node, NodeID
|
|
6
|
+
from strawberry.types import Info
|
|
7
|
+
|
|
8
|
+
from phoenix.db.models import ApiKey as OrmApiKey
|
|
9
|
+
from phoenix.server.api.context import Context
|
|
3
10
|
|
|
4
11
|
from .ApiKey import ApiKey
|
|
5
12
|
|
|
6
13
|
|
|
7
14
|
@strawberry.type
|
|
8
15
|
class SystemApiKey(ApiKey, Node):
|
|
9
|
-
|
|
16
|
+
id: NodeID[int]
|
|
17
|
+
db_record: strawberry.Private[Optional[OrmApiKey]] = None
|
|
18
|
+
|
|
19
|
+
def __post_init__(self) -> None:
|
|
20
|
+
if self.db_record and self.id != self.db_record.id:
|
|
21
|
+
raise ValueError("SystemApiKey ID mismatch")
|
|
22
|
+
|
|
23
|
+
@strawberry.field(description="Name of the API key.") # type: ignore
|
|
24
|
+
async def name(
|
|
25
|
+
self,
|
|
26
|
+
info: Info[Context, None],
|
|
27
|
+
) -> str:
|
|
28
|
+
if self.db_record:
|
|
29
|
+
val = self.db_record.name
|
|
30
|
+
else:
|
|
31
|
+
val = await info.context.data_loaders.user_api_key_fields.load(
|
|
32
|
+
(self.id, OrmApiKey.name),
|
|
33
|
+
)
|
|
34
|
+
return val
|
|
35
|
+
|
|
36
|
+
@strawberry.field(description="Description of the API key.") # type: ignore
|
|
37
|
+
async def description(
|
|
38
|
+
self,
|
|
39
|
+
info: Info[Context, None],
|
|
40
|
+
) -> Optional[str]:
|
|
41
|
+
if self.db_record:
|
|
42
|
+
val = self.db_record.description
|
|
43
|
+
else:
|
|
44
|
+
val = await info.context.data_loaders.user_api_key_fields.load(
|
|
45
|
+
(self.id, OrmApiKey.description),
|
|
46
|
+
)
|
|
47
|
+
return val
|
|
48
|
+
|
|
49
|
+
@strawberry.field(description="The date and time the API key was created.") # type: ignore
|
|
50
|
+
async def created_at(
|
|
51
|
+
self,
|
|
52
|
+
info: Info[Context, None],
|
|
53
|
+
) -> datetime:
|
|
54
|
+
if self.db_record:
|
|
55
|
+
val = self.db_record.created_at
|
|
56
|
+
else:
|
|
57
|
+
val = await info.context.data_loaders.user_api_key_fields.load(
|
|
58
|
+
(self.id, OrmApiKey.created_at),
|
|
59
|
+
)
|
|
60
|
+
return val
|
|
61
|
+
|
|
62
|
+
@strawberry.field(description="The date and time the API key will expire.") # type: ignore
|
|
63
|
+
async def expires_at(
|
|
64
|
+
self,
|
|
65
|
+
info: Info[Context, None],
|
|
66
|
+
) -> Optional[datetime]:
|
|
67
|
+
if self.db_record:
|
|
68
|
+
val = self.db_record.expires_at
|
|
69
|
+
else:
|
|
70
|
+
val = await info.context.data_loaders.user_api_key_fields.load(
|
|
71
|
+
(self.id, OrmApiKey.expires_at),
|
|
72
|
+
)
|
|
73
|
+
return val
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
import strawberry
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TokenKind(Enum):
|
|
7
|
+
PROMPT = "prompt"
|
|
8
|
+
COMPLETION = "completion"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@strawberry.type
|
|
12
|
+
class TokenPrice:
|
|
13
|
+
token_type: str
|
|
14
|
+
kind: TokenKind
|
|
15
|
+
cost_per_million_tokens: float
|
|
16
|
+
cost_per_token: float
|
|
@@ -3,9 +3,9 @@ import strawberry
|
|
|
3
3
|
|
|
4
4
|
@strawberry.type
|
|
5
5
|
class TokenUsage:
|
|
6
|
-
prompt:
|
|
7
|
-
completion:
|
|
6
|
+
prompt: float = 0
|
|
7
|
+
completion: float = 0
|
|
8
8
|
|
|
9
9
|
@strawberry.field
|
|
10
|
-
async def total(self) ->
|
|
10
|
+
async def total(self) -> float:
|
|
11
11
|
return self.prompt + self.completion
|