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,20 +1,22 @@
|
|
|
1
1
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
2
2
|
from fastapi.security import APIKeyHeader
|
|
3
|
-
from starlette.status import HTTP_403_FORBIDDEN
|
|
4
3
|
|
|
5
|
-
from phoenix.server.bearer_auth import is_authenticated
|
|
4
|
+
from phoenix.server.bearer_auth import PhoenixUser, is_authenticated
|
|
6
5
|
|
|
7
6
|
from .annotation_configs import router as annotation_configs_router
|
|
8
7
|
from .annotations import router as annotations_router
|
|
9
8
|
from .datasets import router as datasets_router
|
|
9
|
+
from .documents import router as documents_router
|
|
10
10
|
from .evaluations import router as evaluations_router
|
|
11
11
|
from .experiment_evaluations import router as experiment_evaluations_router
|
|
12
12
|
from .experiment_runs import router as experiment_runs_router
|
|
13
13
|
from .experiments import router as experiments_router
|
|
14
14
|
from .projects import router as projects_router
|
|
15
15
|
from .prompts import router as prompts_router
|
|
16
|
+
from .sessions import router as sessions_router
|
|
16
17
|
from .spans import router as spans_router
|
|
17
18
|
from .traces import router as traces_router
|
|
19
|
+
from .users import router as users_router
|
|
18
20
|
from .utils import add_errors_to_responses
|
|
19
21
|
|
|
20
22
|
REST_API_VERSION = "1.0"
|
|
@@ -27,7 +29,21 @@ async def prevent_access_in_read_only_mode(request: Request) -> None:
|
|
|
27
29
|
if request.app.state.read_only:
|
|
28
30
|
raise HTTPException(
|
|
29
31
|
detail="The Phoenix REST API is disabled in read-only mode.",
|
|
30
|
-
status_code=
|
|
32
|
+
status_code=403,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def restrict_access_by_viewers(request: Request) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Prevents access to the REST API for viewers, except for GET requests
|
|
39
|
+
and specific allowed POST routes.
|
|
40
|
+
"""
|
|
41
|
+
if request.method == "GET":
|
|
42
|
+
return
|
|
43
|
+
if isinstance(request.user, PhoenixUser) and request.user.is_viewer:
|
|
44
|
+
raise HTTPException(
|
|
45
|
+
status_code=403,
|
|
46
|
+
detail="Viewers cannot perform this action.",
|
|
31
47
|
)
|
|
32
48
|
|
|
33
49
|
|
|
@@ -48,13 +64,14 @@ def create_v1_router(authentication_enabled: bool) -> APIRouter:
|
|
|
48
64
|
)
|
|
49
65
|
)
|
|
50
66
|
dependencies.append(Depends(is_authenticated))
|
|
67
|
+
dependencies.append(Depends(restrict_access_by_viewers))
|
|
51
68
|
|
|
52
69
|
router = APIRouter(
|
|
53
70
|
prefix="/v1",
|
|
54
71
|
dependencies=dependencies,
|
|
55
72
|
responses=add_errors_to_responses(
|
|
56
73
|
[
|
|
57
|
-
|
|
74
|
+
403 # adds a 403 response to routes in the generated OpenAPI schema
|
|
58
75
|
]
|
|
59
76
|
),
|
|
60
77
|
)
|
|
@@ -69,4 +86,7 @@ def create_v1_router(authentication_enabled: bool) -> APIRouter:
|
|
|
69
86
|
router.include_router(evaluations_router)
|
|
70
87
|
router.include_router(prompts_router)
|
|
71
88
|
router.include_router(projects_router)
|
|
89
|
+
router.include_router(sessions_router)
|
|
90
|
+
router.include_router(documents_router)
|
|
91
|
+
router.include_router(users_router)
|
|
72
92
|
return router
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Annotated, List, Literal, Optional, Union
|
|
3
3
|
|
|
4
|
-
from fastapi import APIRouter, HTTPException, Path, Query
|
|
4
|
+
from fastapi import APIRouter, Depends, HTTPException, Path, Query
|
|
5
5
|
from pydantic import Field, RootModel
|
|
6
6
|
from sqlalchemy import delete, select
|
|
7
7
|
from sqlalchemy.exc import IntegrityError as PostgreSQLIntegrityError
|
|
8
8
|
from sqlean.dbapi2 import IntegrityError as SQLiteIntegrityError # type: ignore[import-untyped]
|
|
9
9
|
from starlette.requests import Request
|
|
10
|
-
from starlette.status import (
|
|
11
|
-
HTTP_400_BAD_REQUEST,
|
|
12
|
-
HTTP_404_NOT_FOUND,
|
|
13
|
-
HTTP_409_CONFLICT,
|
|
14
|
-
)
|
|
15
10
|
from strawberry.relay import GlobalID
|
|
16
11
|
from typing_extensions import TypeAlias, assert_never
|
|
17
12
|
|
|
@@ -44,6 +39,7 @@ from phoenix.server.api.types.AnnotationConfig import (
|
|
|
44
39
|
from phoenix.server.api.types.AnnotationConfig import (
|
|
45
40
|
FreeformAnnotationConfig as FreeformAnnotationConfigType,
|
|
46
41
|
)
|
|
42
|
+
from phoenix.server.authorization import is_not_locked
|
|
47
43
|
|
|
48
44
|
logger = logging.getLogger(__name__)
|
|
49
45
|
|
|
@@ -205,7 +201,7 @@ async def list_annotation_configs(
|
|
|
205
201
|
except ValueError:
|
|
206
202
|
raise HTTPException(
|
|
207
203
|
detail=f"Invalid cursor: {cursor}",
|
|
208
|
-
status_code=
|
|
204
|
+
status_code=400,
|
|
209
205
|
)
|
|
210
206
|
if cursor_gid.type_name not in (
|
|
211
207
|
CategoricalAnnotationConfigType.__name__,
|
|
@@ -214,7 +210,7 @@ async def list_annotation_configs(
|
|
|
214
210
|
):
|
|
215
211
|
raise HTTPException(
|
|
216
212
|
detail=f"Invalid cursor: {cursor}",
|
|
217
|
-
status_code=
|
|
213
|
+
status_code=400,
|
|
218
214
|
)
|
|
219
215
|
cursor_id = int(cursor_gid.node_id)
|
|
220
216
|
|
|
@@ -260,14 +256,13 @@ async def get_annotation_config_by_name_or_id(
|
|
|
260
256
|
query = query.where(models.AnnotationConfig.name == config_identifier)
|
|
261
257
|
config = await session.scalar(query)
|
|
262
258
|
if not config:
|
|
263
|
-
raise HTTPException(
|
|
264
|
-
status_code=HTTP_404_NOT_FOUND, detail="Annotation configuration not found"
|
|
265
|
-
)
|
|
259
|
+
raise HTTPException(status_code=404, detail="Annotation configuration not found")
|
|
266
260
|
return GetAnnotationConfigResponseBody(data=db_to_api_annotation_config(config))
|
|
267
261
|
|
|
268
262
|
|
|
269
263
|
@router.post(
|
|
270
264
|
"/annotation_configs",
|
|
265
|
+
dependencies=[Depends(is_not_locked)],
|
|
271
266
|
summary="Create an annotation configuration",
|
|
272
267
|
)
|
|
273
268
|
async def create_annotation_config(
|
|
@@ -280,7 +275,7 @@ async def create_annotation_config(
|
|
|
280
275
|
try:
|
|
281
276
|
db_config = _to_db_annotation_config(input_config)
|
|
282
277
|
except ValueError as error:
|
|
283
|
-
raise HTTPException(status_code=
|
|
278
|
+
raise HTTPException(status_code=400, detail=str(error))
|
|
284
279
|
|
|
285
280
|
async with request.app.state.db() as session:
|
|
286
281
|
annotation_config = models.AnnotationConfig(
|
|
@@ -292,7 +287,7 @@ async def create_annotation_config(
|
|
|
292
287
|
await session.commit()
|
|
293
288
|
except (PostgreSQLIntegrityError, SQLiteIntegrityError):
|
|
294
289
|
raise HTTPException(
|
|
295
|
-
status_code=
|
|
290
|
+
status_code=409,
|
|
296
291
|
detail="The name of the annotation configuration is already taken",
|
|
297
292
|
)
|
|
298
293
|
return CreateAnnotationConfigResponseBody(
|
|
@@ -302,6 +297,7 @@ async def create_annotation_config(
|
|
|
302
297
|
|
|
303
298
|
@router.put(
|
|
304
299
|
"/annotation_configs/{config_id}",
|
|
300
|
+
dependencies=[Depends(is_not_locked)],
|
|
305
301
|
summary="Update an annotation configuration",
|
|
306
302
|
)
|
|
307
303
|
async def update_annotation_config(
|
|
@@ -318,22 +314,18 @@ async def update_annotation_config(
|
|
|
318
314
|
ContinuousAnnotationConfigType.__name__,
|
|
319
315
|
FreeformAnnotationConfigType.__name__,
|
|
320
316
|
):
|
|
321
|
-
raise HTTPException(
|
|
322
|
-
status_code=HTTP_400_BAD_REQUEST, detail="Invalid annotation configuration ID"
|
|
323
|
-
)
|
|
317
|
+
raise HTTPException(status_code=400, detail="Invalid annotation configuration ID")
|
|
324
318
|
config_rowid = int(config_gid.node_id)
|
|
325
319
|
|
|
326
320
|
try:
|
|
327
321
|
db_config = _to_db_annotation_config(input_config)
|
|
328
322
|
except ValueError as error:
|
|
329
|
-
raise HTTPException(status_code=
|
|
323
|
+
raise HTTPException(status_code=400, detail=str(error))
|
|
330
324
|
|
|
331
325
|
async with request.app.state.db() as session:
|
|
332
326
|
existing_config = await session.get(models.AnnotationConfig, config_rowid)
|
|
333
327
|
if not existing_config:
|
|
334
|
-
raise HTTPException(
|
|
335
|
-
status_code=HTTP_404_NOT_FOUND, detail="Annotation configuration not found"
|
|
336
|
-
)
|
|
328
|
+
raise HTTPException(status_code=404, detail="Annotation configuration not found")
|
|
337
329
|
|
|
338
330
|
existing_config.name = input_config.name
|
|
339
331
|
existing_config.config = db_config
|
|
@@ -342,7 +334,7 @@ async def update_annotation_config(
|
|
|
342
334
|
await session.commit()
|
|
343
335
|
except (PostgreSQLIntegrityError, SQLiteIntegrityError):
|
|
344
336
|
raise HTTPException(
|
|
345
|
-
status_code=
|
|
337
|
+
status_code=409,
|
|
346
338
|
detail="The name of the annotation configuration is already taken",
|
|
347
339
|
)
|
|
348
340
|
|
|
@@ -357,15 +349,19 @@ async def delete_annotation_config(
|
|
|
357
349
|
request: Request,
|
|
358
350
|
config_id: str = Path(..., description="ID of the annotation configuration"),
|
|
359
351
|
) -> DeleteAnnotationConfigResponseBody:
|
|
360
|
-
|
|
352
|
+
try:
|
|
353
|
+
config_gid = GlobalID.from_id(config_id)
|
|
354
|
+
except Exception:
|
|
355
|
+
raise HTTPException(
|
|
356
|
+
status_code=422,
|
|
357
|
+
detail=f"Invalid annotation configuration ID format: {config_id}",
|
|
358
|
+
)
|
|
361
359
|
if config_gid.type_name not in (
|
|
362
360
|
CategoricalAnnotationConfigType.__name__,
|
|
363
361
|
ContinuousAnnotationConfigType.__name__,
|
|
364
362
|
FreeformAnnotationConfigType.__name__,
|
|
365
363
|
):
|
|
366
|
-
raise HTTPException(
|
|
367
|
-
status_code=HTTP_400_BAD_REQUEST, detail="Invalid annotation configuration ID"
|
|
368
|
-
)
|
|
364
|
+
raise HTTPException(status_code=400, detail="Invalid annotation configuration ID")
|
|
369
365
|
config_rowid = int(config_gid.node_id)
|
|
370
366
|
async with request.app.state.db() as session:
|
|
371
367
|
stmt = (
|
|
@@ -375,9 +371,7 @@ async def delete_annotation_config(
|
|
|
375
371
|
)
|
|
376
372
|
annotation_config = await session.scalar(stmt)
|
|
377
373
|
if annotation_config is None:
|
|
378
|
-
raise HTTPException(
|
|
379
|
-
status_code=HTTP_404_NOT_FOUND, detail="Annotation configuration not found"
|
|
380
|
-
)
|
|
374
|
+
raise HTTPException(status_code=404, detail="Annotation configuration not found")
|
|
381
375
|
await session.commit()
|
|
382
376
|
return DeleteAnnotationConfigResponseBody(data=db_to_api_annotation_config(annotation_config))
|
|
383
377
|
|
|
@@ -397,9 +391,7 @@ def _get_annotation_config_db_id(config_gid: str) -> int:
|
|
|
397
391
|
def _reserve_note_annotation_name(data: AnnotationConfigData) -> str:
|
|
398
392
|
name = data.name
|
|
399
393
|
if name == "note":
|
|
400
|
-
raise HTTPException(
|
|
401
|
-
status_code=HTTP_409_CONFLICT, detail="The name 'note' is reserved for span notes"
|
|
402
|
-
)
|
|
394
|
+
raise HTTPException(status_code=409, detail="The name 'note' is reserved for span notes")
|
|
403
395
|
return name
|
|
404
396
|
|
|
405
397
|
|