arize-phoenix 4.7.2__py3-none-any.whl → 4.8.0__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.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-4.7.2.dist-info → arize_phoenix-4.8.0.dist-info}/METADATA +1 -1
- {arize_phoenix-4.7.2.dist-info → arize_phoenix-4.8.0.dist-info}/RECORD +14 -13
- phoenix/db/helpers.py +37 -2
- phoenix/server/api/dataloaders/project_by_name.py +1 -1
- phoenix/server/api/mutations/dataset_mutations.py +23 -13
- phoenix/server/api/mutations/experiment_mutations.py +12 -4
- phoenix/server/api/routers/v1/__init__.py +1 -0
- phoenix/server/api/routers/v1/datasets.py +59 -1
- phoenix/server/api/utils.py +36 -0
- phoenix/server/static/index.js +2 -2
- phoenix/version.py +1 -1
- {arize_phoenix-4.7.2.dist-info → arize_phoenix-4.8.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.7.2.dist-info → arize_phoenix-4.8.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.7.2.dist-info → arize_phoenix-4.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,7 +5,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
|
5
5
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
6
6
|
phoenix/services.py,sha256=aTxhcOA1pZHB6U-B3TEcp6fqDF5oT0xCUvEUNMZVTUQ,5175
|
|
7
7
|
phoenix/settings.py,sha256=cO-qgis_S27nHirTobYI9hHPfZH18R--WMmxNdsVUwc,273
|
|
8
|
-
phoenix/version.py,sha256=
|
|
8
|
+
phoenix/version.py,sha256=NsvNfym-LKhyklkaZu-iwzlvcIWUdbdxxglpRMhC1TU,22
|
|
9
9
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
11
11
|
phoenix/core/model.py,sha256=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
|
|
@@ -16,7 +16,7 @@ phoenix/db/__init__.py,sha256=pDjEFXukHmJBM-1D8RjmXkvLsz85YWNxMQczt81ec3A,118
|
|
|
16
16
|
phoenix/db/alembic.ini,sha256=p8DjVqGUs_tTx8oU56JP7qj-rMUebNFizItUSv_hPhs,3763
|
|
17
17
|
phoenix/db/bulk_inserter.py,sha256=zbZGWZFDybKaGLGzpxgLwxAS5sC0_wXcvM0be4kUhh8,11286
|
|
18
18
|
phoenix/db/engines.py,sha256=vLWaZlToMtDI7rJDxSidYkfOoojamxaZxaz8ND3zTus,4770
|
|
19
|
-
phoenix/db/helpers.py,sha256=
|
|
19
|
+
phoenix/db/helpers.py,sha256=mTBhPzdy_aU9gD7hNzUZJkAnV77ko5CdaXyoWH3snPA,2982
|
|
20
20
|
phoenix/db/migrate.py,sha256=MuhtNWnR24riROvarvKfbRb4_D5xuQi6P760vBUKl1E,2270
|
|
21
21
|
phoenix/db/models.py,sha256=7DBWbxY3cx3ve2P1I0kkDKXzlt04zEFJuRPJWsVpH-I,20422
|
|
22
22
|
phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -71,6 +71,7 @@ phoenix/server/api/context.py,sha256=4jcy203Gtx38399FP21iU3HmFsq-50EKFJlX4IW2Los
|
|
|
71
71
|
phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
|
|
72
72
|
phoenix/server/api/queries.py,sha256=wp5BlapuxDIoaQJm7mzG0dURfVxR32vXSJVC0JqG4_Y,19845
|
|
73
73
|
phoenix/server/api/schema.py,sha256=BcxdqO5CSGqpKd-AAJHMjFlzaK9oJA8GJuxmMfcdjn4,434
|
|
74
|
+
phoenix/server/api/utils.py,sha256=Y1lGu8J8r8BSBX9OzffgewI8QMziovbG-ePDvZrrwGI,949
|
|
74
75
|
phoenix/server/api/dataloaders/__init__.py,sha256=qehXL37vGdw7v5PFs3kbZVIuhuzrVNVeZACDQjYpwyo,4847
|
|
75
76
|
phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=RiO0AKC6Y5byafsV0zTJEIOt8Nudjte73f1T78cBe1k,1817
|
|
76
77
|
phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=Vpr5IEKSR4QnAVxE5NM7u92fPNgeHQV2ieYc6JakCj0,3788
|
|
@@ -85,7 +86,7 @@ phoenix/server/api/dataloaders/experiment_run_counts.py,sha256=wxHv08aZELJ91KTjH
|
|
|
85
86
|
phoenix/server/api/dataloaders/experiment_sequence_number.py,sha256=Va1KuoHOd-wzvrlKykoV4kLRFW4JsJvGp_DUI4HYZX4,1631
|
|
86
87
|
phoenix/server/api/dataloaders/latency_ms_quantile.py,sha256=pEc7QjB2iiNOQm_Fmo99F5O_DKOJWgGmcnT0OADJzYE,7423
|
|
87
88
|
phoenix/server/api/dataloaders/min_start_or_max_end_times.py,sha256=IoFX5PtSpvQdMk_7-oB8TpIse3Q4PMxep4qKggkHpzo,2902
|
|
88
|
-
phoenix/server/api/dataloaders/project_by_name.py,sha256=
|
|
89
|
+
phoenix/server/api/dataloaders/project_by_name.py,sha256=W4q-ddeVnja2DNwgg5l8mV2GNADNJf1CTXNcJaBWdfE,1165
|
|
89
90
|
phoenix/server/api/dataloaders/record_counts.py,sha256=mp3KlhwFw-Iy7o6bFxtJKC6B5kGinPIh5PxxNkrxf8o,4283
|
|
90
91
|
phoenix/server/api/dataloaders/span_descendants.py,sha256=djqXXwupWaXkFdscoy-iILYijuxlqr8hJcv6JawsV6s,2162
|
|
91
92
|
phoenix/server/api/dataloaders/span_evaluations.py,sha256=quXGyj_OYvHrcWfzXlYIv7C1OCZiL1K7cWU-YEAlsNA,1316
|
|
@@ -121,8 +122,8 @@ phoenix/server/api/input_types/TimeRange.py,sha256=yzx-gxj8mDeGLft1FzU_x1MVEgIG5
|
|
|
121
122
|
phoenix/server/api/input_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
123
|
phoenix/server/api/mutations/__init__.py,sha256=Jcz-pM6SklhEGKcjA7AIB2WJXGhnxGsghrIq131kyDo,502
|
|
123
124
|
phoenix/server/api/mutations/auth.py,sha256=vPRFoj7J6PV6QeODewG4K0PhoOebS5AfMRpbi_wuhyQ,311
|
|
124
|
-
phoenix/server/api/mutations/dataset_mutations.py,sha256=
|
|
125
|
-
phoenix/server/api/mutations/experiment_mutations.py,sha256=
|
|
125
|
+
phoenix/server/api/mutations/dataset_mutations.py,sha256=CuKhxsYfvwVcdN_9EXhKxB6444BQfObzKzzyfAeg-n8,23199
|
|
126
|
+
phoenix/server/api/mutations/experiment_mutations.py,sha256=vV2lbJ7ccXZqe-LY7nXx6QxWqhKQE4UNZAFcML-KQ8I,3011
|
|
126
127
|
phoenix/server/api/mutations/export_events_mutations.py,sha256=t_wYBxaqvBJYRoHslh3Bmoxmwlzoy0u8SsBKWIKN5hE,4028
|
|
127
128
|
phoenix/server/api/mutations/project_mutations.py,sha256=3SVDCZqxB0Iv60cOwBL8c-rY3QUUPs8PXbp-C_K1mWY,2267
|
|
128
129
|
phoenix/server/api/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -130,9 +131,9 @@ phoenix/server/api/openapi/main.py,sha256=WY0pj3B7siQyyYqKyhqnzWC7P8MtEtiukOBUjG
|
|
|
130
131
|
phoenix/server/api/openapi/schema.py,sha256=uuSYe1Ecu72aXRgTNjyMu-9ZPE13DAHJPKtedS-MsSs,451
|
|
131
132
|
phoenix/server/api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
132
133
|
phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
|
|
133
|
-
phoenix/server/api/routers/v1/__init__.py,sha256=
|
|
134
|
+
phoenix/server/api/routers/v1/__init__.py,sha256=Ir5fsO6gQXW58HGm7s2sMUq0vya7mfcWneLcLJy6_q8,2895
|
|
134
135
|
phoenix/server/api/routers/v1/dataset_examples.py,sha256=XfqOvDKF1oxb0pkeYfBycwwGt3LnSyyGdMLKC5VKoGQ,6690
|
|
135
|
-
phoenix/server/api/routers/v1/datasets.py,sha256=
|
|
136
|
+
phoenix/server/api/routers/v1/datasets.py,sha256=r0WcNxF8SKVa3-4rrTIg4Andwr4NmRmW1ybpKuxR9qw,33639
|
|
136
137
|
phoenix/server/api/routers/v1/evaluations.py,sha256=8g6P_e2BweV3RDU0esFmpkb0L5fCwonQPXiJ0y6HLwg,9126
|
|
137
138
|
phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=H_psVyuGUQImo0oxdEAKAMQ-oyVwkVIq5yaMHzHIiPc,5455
|
|
138
139
|
phoenix/server/api/routers/v1/experiment_runs.py,sha256=jy4SynmzdtQMoUzlowmG6wsVU14SsLAzfcW4JOhXjeQ,8154
|
|
@@ -202,7 +203,7 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
202
203
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
203
204
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
204
205
|
phoenix/server/static/index.css,sha256=KKGpx4iwF91VGRm0YN-4cn8oC-oIqC6HecoPf0x3ZM8,1885
|
|
205
|
-
phoenix/server/static/index.js,sha256=
|
|
206
|
+
phoenix/server/static/index.js,sha256=sUkm_imwx5uXpCQxQEPmX-axDr094HE1wGdBznF8J_E,3524949
|
|
206
207
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
207
208
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
208
209
|
phoenix/server/templates/index.html,sha256=S4z7qSoNSwnKFAH9r96AR-YJEyoKMd-VMWVlJ_IdzME,2039
|
|
@@ -247,8 +248,8 @@ phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,
|
|
|
247
248
|
phoenix/utilities/project.py,sha256=qWsvKnG1oKhOFUowXf9qiOL2ia7jaFe_ijFFHEt8GJo,431
|
|
248
249
|
phoenix/utilities/re.py,sha256=PDve_OLjRTM8yQQJHC8-n3HdIONi7aNils3ZKRZ5uBM,2045
|
|
249
250
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
250
|
-
arize_phoenix-4.
|
|
251
|
-
arize_phoenix-4.
|
|
252
|
-
arize_phoenix-4.
|
|
253
|
-
arize_phoenix-4.
|
|
254
|
-
arize_phoenix-4.
|
|
251
|
+
arize_phoenix-4.8.0.dist-info/METADATA,sha256=UNwc2BbfIMe5RbFT-IuzfKQnX21dFA4zY5EUXbo5bC8,11451
|
|
252
|
+
arize_phoenix-4.8.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
253
|
+
arize_phoenix-4.8.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
254
|
+
arize_phoenix-4.8.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
255
|
+
arize_phoenix-4.8.0.dist-info/RECORD,,
|
phoenix/db/helpers.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any, Optional, Tuple
|
|
3
3
|
|
|
4
4
|
from openinference.semconv.trace import (
|
|
5
5
|
OpenInferenceSpanKindValues,
|
|
6
6
|
RerankerAttributes,
|
|
7
7
|
SpanAttributes,
|
|
8
8
|
)
|
|
9
|
-
from sqlalchemy import Integer, SQLColumnExpression, case, func
|
|
9
|
+
from sqlalchemy import Integer, Select, SQLColumnExpression, case, distinct, func, select
|
|
10
10
|
from typing_extensions import assert_never
|
|
11
11
|
|
|
12
12
|
from phoenix.db import models
|
|
@@ -45,3 +45,38 @@ def num_docs_col(dialect: SupportedSQLDialect) -> SQLColumnExpression[Integer]:
|
|
|
45
45
|
|
|
46
46
|
_RETRIEVAL_DOCUMENTS = SpanAttributes.RETRIEVAL_DOCUMENTS.split(".")
|
|
47
47
|
_RERANKER_OUTPUT_DOCUMENTS = RerankerAttributes.RERANKER_OUTPUT_DOCUMENTS.split(".")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_eval_trace_ids_for_datasets(*dataset_ids: int) -> Select[Tuple[Optional[str]]]:
|
|
51
|
+
return (
|
|
52
|
+
select(distinct(models.ExperimentRunAnnotation.trace_id))
|
|
53
|
+
.join(models.ExperimentRun)
|
|
54
|
+
.join_from(models.ExperimentRun, models.Experiment)
|
|
55
|
+
.where(models.Experiment.dataset_id.in_(set(dataset_ids)))
|
|
56
|
+
.where(models.ExperimentRunAnnotation.trace_id.isnot(None))
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_project_names_for_datasets(*dataset_ids: int) -> Select[Tuple[Optional[str]]]:
|
|
61
|
+
return (
|
|
62
|
+
select(distinct(models.Experiment.project_name))
|
|
63
|
+
.where(models.Experiment.dataset_id.in_(set(dataset_ids)))
|
|
64
|
+
.where(models.Experiment.project_name.isnot(None))
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_eval_trace_ids_for_experiments(*experiment_ids: int) -> Select[Tuple[Optional[str]]]:
|
|
69
|
+
return (
|
|
70
|
+
select(distinct(models.ExperimentRunAnnotation.trace_id))
|
|
71
|
+
.join(models.ExperimentRun)
|
|
72
|
+
.where(models.ExperimentRun.experiment_id.in_(set(experiment_ids)))
|
|
73
|
+
.where(models.ExperimentRunAnnotation.trace_id.isnot(None))
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_project_names_for_experiments(*experiment_ids: int) -> Select[Tuple[Optional[str]]]:
|
|
78
|
+
return (
|
|
79
|
+
select(distinct(models.Experiment.project_name))
|
|
80
|
+
.where(models.Experiment.id.in_(set(experiment_ids)))
|
|
81
|
+
.where(models.Experiment.project_name.isnot(None))
|
|
82
|
+
)
|
|
@@ -28,4 +28,4 @@ class ProjectByNameDataLoader(DataLoader[Key, Result]):
|
|
|
28
28
|
async for project in data:
|
|
29
29
|
projects_by_name[project.name] = project
|
|
30
30
|
|
|
31
|
-
return [projects_by_name
|
|
31
|
+
return [projects_by_name.get(project_name) for project_name in keys]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from datetime import datetime
|
|
2
3
|
from typing import Any, Dict
|
|
3
4
|
|
|
@@ -10,6 +11,7 @@ from strawberry import UNSET
|
|
|
10
11
|
from strawberry.types import Info
|
|
11
12
|
|
|
12
13
|
from phoenix.db import models
|
|
14
|
+
from phoenix.db.helpers import get_eval_trace_ids_for_datasets, get_project_names_for_datasets
|
|
13
15
|
from phoenix.server.api.context import Context
|
|
14
16
|
from phoenix.server.api.helpers.dataset_helpers import (
|
|
15
17
|
get_dataset_example_input,
|
|
@@ -30,6 +32,7 @@ from phoenix.server.api.types.Dataset import Dataset, to_gql_dataset
|
|
|
30
32
|
from phoenix.server.api.types.DatasetExample import DatasetExample
|
|
31
33
|
from phoenix.server.api.types.node import from_global_id_with_expected_type
|
|
32
34
|
from phoenix.server.api.types.Span import Span
|
|
35
|
+
from phoenix.server.api.utils import delete_projects, delete_traces
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
@strawberry.type
|
|
@@ -274,21 +277,28 @@ class DatasetMutationMixin:
|
|
|
274
277
|
info: Info[Context, None],
|
|
275
278
|
input: DeleteDatasetInput,
|
|
276
279
|
) -> DatasetMutationPayload:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
+
try:
|
|
281
|
+
dataset_id = from_global_id_with_expected_type(
|
|
282
|
+
global_id=input.dataset_id,
|
|
283
|
+
expected_type_name=Dataset.__name__,
|
|
284
|
+
)
|
|
285
|
+
except ValueError:
|
|
286
|
+
raise ValueError(f"Unknown dataset: {input.dataset_id}")
|
|
287
|
+
project_names_stmt = get_project_names_for_datasets(dataset_id)
|
|
288
|
+
eval_trace_ids_stmt = get_eval_trace_ids_for_datasets(dataset_id)
|
|
289
|
+
stmt = (
|
|
290
|
+
delete(models.Dataset).where(models.Dataset.id == dataset_id).returning(models.Dataset)
|
|
280
291
|
)
|
|
281
|
-
|
|
282
292
|
async with info.context.db() as session:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
293
|
+
project_names = await session.scalars(project_names_stmt)
|
|
294
|
+
eval_trace_ids = await session.scalars(eval_trace_ids_stmt)
|
|
295
|
+
if not (dataset := await session.scalar(stmt)):
|
|
296
|
+
raise ValueError(f"Unknown dataset: {input.dataset_id}")
|
|
297
|
+
await asyncio.gather(
|
|
298
|
+
delete_projects(info.context.db, *project_names),
|
|
299
|
+
delete_traces(info.context.db, *eval_trace_ids),
|
|
300
|
+
return_exceptions=True,
|
|
301
|
+
)
|
|
292
302
|
return DatasetMutationPayload(dataset=to_gql_dataset(dataset))
|
|
293
303
|
|
|
294
304
|
@strawberry.mutation(permission_classes=[IsAuthenticated]) # type: ignore
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from typing import List
|
|
2
3
|
|
|
3
4
|
import strawberry
|
|
@@ -6,11 +7,13 @@ from strawberry.relay import GlobalID
|
|
|
6
7
|
from strawberry.types import Info
|
|
7
8
|
|
|
8
9
|
from phoenix.db import models
|
|
10
|
+
from phoenix.db.helpers import get_eval_trace_ids_for_experiments, get_project_names_for_experiments
|
|
9
11
|
from phoenix.server.api.context import Context
|
|
10
12
|
from phoenix.server.api.input_types.DeleteExperimentsInput import DeleteExperimentsInput
|
|
11
13
|
from phoenix.server.api.mutations.auth import IsAuthenticated
|
|
12
14
|
from phoenix.server.api.types.Experiment import Experiment, to_gql_experiment
|
|
13
15
|
from phoenix.server.api.types.node import from_global_id_with_expected_type
|
|
16
|
+
from phoenix.server.api.utils import delete_projects, delete_traces
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
@strawberry.type
|
|
@@ -30,7 +33,11 @@ class ExperimentMutationMixin:
|
|
|
30
33
|
from_global_id_with_expected_type(experiment_id, Experiment.__name__)
|
|
31
34
|
for experiment_id in input.experiment_ids
|
|
32
35
|
]
|
|
36
|
+
project_names_stmt = get_project_names_for_experiments(*experiment_ids)
|
|
37
|
+
eval_trace_ids_stmt = get_eval_trace_ids_for_experiments(*experiment_ids)
|
|
33
38
|
async with info.context.db() as session:
|
|
39
|
+
project_names = await session.scalars(project_names_stmt)
|
|
40
|
+
eval_trace_ids = await session.scalars(eval_trace_ids_stmt)
|
|
34
41
|
savepoint = await session.begin_nested()
|
|
35
42
|
experiments = {
|
|
36
43
|
experiment.id: experiment
|
|
@@ -54,10 +61,11 @@ class ExperimentMutationMixin:
|
|
|
54
61
|
]
|
|
55
62
|
)
|
|
56
63
|
)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
await asyncio.gather(
|
|
65
|
+
delete_projects(info.context.db, *project_names),
|
|
66
|
+
delete_traces(info.context.db, *eval_trace_ids),
|
|
67
|
+
return_exceptions=True,
|
|
68
|
+
)
|
|
61
69
|
return ExperimentMutationPayload(
|
|
62
70
|
experiments=[
|
|
63
71
|
to_gql_experiment(experiments[experiment_id]) for experiment_id in experiment_ids
|
|
@@ -44,6 +44,7 @@ V1_ROUTES = [
|
|
|
44
44
|
Route("/v1/spans", spans.get_spans_handler, methods=["GET"]),
|
|
45
45
|
Route("/v1/datasets/upload", datasets.post_datasets_upload, methods=["POST"]),
|
|
46
46
|
Route("/v1/datasets", datasets.list_datasets, methods=["GET"]),
|
|
47
|
+
Route("/v1/datasets/{id:str}", datasets.delete_dataset_by_id, methods=["DELETE"]),
|
|
47
48
|
Route("/v1/datasets/{id:str}", datasets.get_dataset_by_id, methods=["GET"]),
|
|
48
49
|
Route("/v1/datasets/{id:str}/csv", datasets.get_dataset_csv, methods=["GET"]),
|
|
49
50
|
Route(
|
|
@@ -26,13 +26,15 @@ from typing import (
|
|
|
26
26
|
|
|
27
27
|
import pandas as pd
|
|
28
28
|
import pyarrow as pa
|
|
29
|
-
from sqlalchemy import and_, func, select
|
|
29
|
+
from sqlalchemy import and_, delete, func, select
|
|
30
30
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
31
|
+
from starlette.background import BackgroundTasks
|
|
31
32
|
from starlette.concurrency import run_in_threadpool
|
|
32
33
|
from starlette.datastructures import FormData, UploadFile
|
|
33
34
|
from starlette.requests import Request
|
|
34
35
|
from starlette.responses import JSONResponse, Response
|
|
35
36
|
from starlette.status import (
|
|
37
|
+
HTTP_204_NO_CONTENT,
|
|
36
38
|
HTTP_404_NOT_FOUND,
|
|
37
39
|
HTTP_409_CONFLICT,
|
|
38
40
|
HTTP_422_UNPROCESSABLE_ENTITY,
|
|
@@ -42,6 +44,7 @@ from strawberry.relay import GlobalID
|
|
|
42
44
|
from typing_extensions import TypeAlias, assert_never
|
|
43
45
|
|
|
44
46
|
from phoenix.db import models
|
|
47
|
+
from phoenix.db.helpers import get_eval_trace_ids_for_datasets, get_project_names_for_datasets
|
|
45
48
|
from phoenix.db.insertion.dataset import (
|
|
46
49
|
DatasetAction,
|
|
47
50
|
DatasetExampleAdditionEvent,
|
|
@@ -52,6 +55,7 @@ from phoenix.server.api.types.Dataset import Dataset
|
|
|
52
55
|
from phoenix.server.api.types.DatasetExample import DatasetExample
|
|
53
56
|
from phoenix.server.api.types.DatasetVersion import DatasetVersion
|
|
54
57
|
from phoenix.server.api.types.node import from_global_id_with_expected_type
|
|
58
|
+
from phoenix.server.api.utils import delete_projects, delete_traces
|
|
55
59
|
|
|
56
60
|
logger = logging.getLogger(__name__)
|
|
57
61
|
|
|
@@ -163,6 +167,60 @@ async def list_datasets(request: Request) -> Response:
|
|
|
163
167
|
return JSONResponse(content={"next_cursor": next_cursor, "data": data})
|
|
164
168
|
|
|
165
169
|
|
|
170
|
+
async def delete_dataset_by_id(request: Request) -> Response:
|
|
171
|
+
"""
|
|
172
|
+
summary: Delete dataset by ID
|
|
173
|
+
operationId: deleteDatasetById
|
|
174
|
+
tags:
|
|
175
|
+
- datasets
|
|
176
|
+
parameters:
|
|
177
|
+
- in: path
|
|
178
|
+
name: id
|
|
179
|
+
required: true
|
|
180
|
+
schema:
|
|
181
|
+
type: string
|
|
182
|
+
responses:
|
|
183
|
+
204:
|
|
184
|
+
description: Success
|
|
185
|
+
403:
|
|
186
|
+
description: Forbidden
|
|
187
|
+
404:
|
|
188
|
+
description: Dataset not found
|
|
189
|
+
422:
|
|
190
|
+
description: Dataset ID is invalid
|
|
191
|
+
"""
|
|
192
|
+
if id_ := request.path_params.get("id"):
|
|
193
|
+
try:
|
|
194
|
+
dataset_id = from_global_id_with_expected_type(
|
|
195
|
+
GlobalID.from_id(id_),
|
|
196
|
+
Dataset.__name__,
|
|
197
|
+
)
|
|
198
|
+
except ValueError:
|
|
199
|
+
return Response(
|
|
200
|
+
content=f"Invalid Dataset ID: {id_}",
|
|
201
|
+
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
return Response(
|
|
205
|
+
content="Missing Dataset ID",
|
|
206
|
+
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
|
|
207
|
+
)
|
|
208
|
+
project_names_stmt = get_project_names_for_datasets(dataset_id)
|
|
209
|
+
eval_trace_ids_stmt = get_eval_trace_ids_for_datasets(dataset_id)
|
|
210
|
+
stmt = (
|
|
211
|
+
delete(models.Dataset).where(models.Dataset.id == dataset_id).returning(models.Dataset.id)
|
|
212
|
+
)
|
|
213
|
+
async with request.app.state.db() as session:
|
|
214
|
+
project_names = await session.scalars(project_names_stmt)
|
|
215
|
+
eval_trace_ids = await session.scalars(eval_trace_ids_stmt)
|
|
216
|
+
if (await session.scalar(stmt)) is None:
|
|
217
|
+
return Response(content="Dataset does not exist", status_code=HTTP_404_NOT_FOUND)
|
|
218
|
+
tasks = BackgroundTasks()
|
|
219
|
+
tasks.add_task(delete_projects, request.app.state.db, *project_names)
|
|
220
|
+
tasks.add_task(delete_traces, request.app.state.db, *eval_trace_ids)
|
|
221
|
+
return Response(status_code=HTTP_204_NO_CONTENT, background=tasks)
|
|
222
|
+
|
|
223
|
+
|
|
166
224
|
async def get_dataset_by_id(request: Request) -> Response:
|
|
167
225
|
"""
|
|
168
226
|
summary: Get dataset by ID
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typing import AsyncContextManager, Callable, List
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import delete
|
|
4
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
5
|
+
|
|
6
|
+
from phoenix.db import models
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def delete_projects(
|
|
10
|
+
db: Callable[[], AsyncContextManager[AsyncSession]],
|
|
11
|
+
*project_names: str,
|
|
12
|
+
) -> List[int]:
|
|
13
|
+
if not project_names:
|
|
14
|
+
return []
|
|
15
|
+
stmt = (
|
|
16
|
+
delete(models.Project)
|
|
17
|
+
.where(models.Project.name.in_(set(project_names)))
|
|
18
|
+
.returning(models.Project.id)
|
|
19
|
+
)
|
|
20
|
+
async with db() as session:
|
|
21
|
+
return list(await session.scalars(stmt))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def delete_traces(
|
|
25
|
+
db: Callable[[], AsyncContextManager[AsyncSession]],
|
|
26
|
+
*trace_ids: str,
|
|
27
|
+
) -> List[int]:
|
|
28
|
+
if not trace_ids:
|
|
29
|
+
return []
|
|
30
|
+
stmt = (
|
|
31
|
+
delete(models.Trace)
|
|
32
|
+
.where(models.Trace.trace_id.in_(set(trace_ids)))
|
|
33
|
+
.returning(models.Trace.id)
|
|
34
|
+
)
|
|
35
|
+
async with db() as session:
|
|
36
|
+
return list(await session.scalars(stmt))
|
phoenix/server/static/index.js
CHANGED
|
@@ -7750,7 +7750,7 @@ fragment DatasetsTable_datasets on Query {
|
|
|
7750
7750
|
__typename
|
|
7751
7751
|
}
|
|
7752
7752
|
}
|
|
7753
|
-
`}}}();bat.hash="d98c682a2c908030c2f772209a4a25b8";var mat=bat;var Q0=P(ie()),Iat=P(wt());function pat(t){let{datasetId:e,datasetName:n,onDatasetDelete:i,onDatasetDeleteError:r}=t,[a,o]=(0,Q0.useState)(null),[l,s]=(0,Iat.useMutation)(mat),c=(0,Q0.useCallback)(()=>{(0,Q0.startTransition)(()=>{l({variables:{datasetId:e},onCompleted:()=>{i()},onError:g=>{r(g)}})})},[l,e,i,r]),u=(0,Q0.useCallback)(()=>{o(B(Mn,{size:"S",title:"Delete Dataset",children:[h(De,{padding:"size-200",children:h(me,{color:"danger",children:`Are you sure you want to delete dataset ${n}? This cannot be undone.`})}),h(De,{paddingEnd:"size-200",paddingTop:"size-100",paddingBottom:"size-100",borderTopColor:"light",borderTopWidth:"thin",children:h(ge,{direction:"row",justifyContent:"end",children:h(At,{variant:"danger",onClick:()=>{c(),o(null)},children:"Delete Dataset"})})})]}))},[c,n]);return B("div",{onClick:g=>{g.preventDefault(),g.stopPropagation()},children:[h(Gc,{align:"end",buttonSize:"compact",isDisabled:s,onAction:g=>{switch(g){case"deleteDataset":u();break}},children:h(Ht,{children:B(ge,{direction:"row",gap:"size-75",justifyContent:"start",alignItems:"center",children:[h(ke,{svg:h(Pe.TrashOutline,{})}),h(me,{children:"Delete"})]})},"deleteDataset")}),h(Fn,{type:"modal",isDismissable:!0,onDismiss:()=>o(null),children:a})]})}var hat=100;function cGn(t){let e=t.id;if(e!=="createdAt"&&e!=="name")throw new Error("Invalid sort column");return{col:e,dir:t.desc?"desc":"asc"}}function Cat(t){let[e,n]=(0,cd.useState)([]),i=(0,cd.useRef)(null),r=Zn(),a=Zo(),o=dm(),{data:l,loadNext:s,hasNext:c,isLoadingNext:u,refetch:g}=(0,fat.usePaginationFragment)(dat,t.query),d=(0,cd.useMemo)(()=>l.datasets.edges.map(f=>f.node),[l]),b=cd.default.useCallback(f=>{if(f){let{scrollHeight:C,scrollTop:v,clientHeight:x}=f;C-v-x<300&&!u&&c&&s(hat)}},[c,u,s]),m=Gr({columns:[{header:"name",accessorKey:"name",cell:({row:f})=>{let v=f.original.experimentCount>0?`${f.original.id}/experiments`:`${f.original.id}/examples`;return h(_l,{to:v,children:f.original.name})}},{header:"description",accessorKey:"description",enableSorting:!1},{header:"created at",accessorKey:"createdAt",cell:sd},{header:"example count",accessorKey:"exampleCount",enableSorting:!1,meta:{textAlign:"right"}},{header:"experiment count",accessorKey:"experimentCount",enableSorting:!1,meta:{textAlign:"right"}},{header:"",id:"actions",enableSorting:!1,size:10,cell:({row:f})=>h(pat,{datasetId:f.original.id,datasetName:f.original.name,onDatasetDelete:()=>{a({title:"Dataset deleted",message:`${f.original.name} has been successfully deleted.`}),g({},{fetchPolicy:"store-and-network"})},onDatasetDeleteError:C=>{o({title:"Dataset deletion failed",message:C.message})}})}],data:d,state:{sorting:e},getCoreRowModel:Wr(),getSortedRowModel:Zg(),onSortingChange:n,manualSorting:!0});(0,cd.useEffect)(()=>{let f=e[0];(0,cd.startTransition)(()=>{g({sort:f?cGn(f):{col:"createdAt",dir:"desc"},after:null,first:hat},{fetchPolicy:"store-and-network"})})},[e,g]);let I=m.getRowModel().rows,p=I.length===0;return h("div",{css:$`
|
|
7753
|
+
`}}}();bat.hash="d98c682a2c908030c2f772209a4a25b8";var mat=bat;var Q0=P(ie()),Iat=P(wt());function pat(t){let{datasetId:e,datasetName:n,onDatasetDelete:i,onDatasetDeleteError:r}=t,[a,o]=(0,Q0.useState)(null),[l,s]=(0,Iat.useMutation)(mat),c=(0,Q0.useCallback)(()=>{(0,Q0.startTransition)(()=>{l({variables:{datasetId:e},onCompleted:()=>{i()},onError:g=>{r(g)}})})},[l,e,i,r]),u=(0,Q0.useCallback)(()=>{o(B(Mn,{size:"S",title:"Delete Dataset",children:[h(De,{padding:"size-200",children:h(me,{color:"danger",children:`Are you sure you want to delete dataset ${n}? This will also delete all associated experiments and traces, and it cannot be undone.`})}),h(De,{paddingEnd:"size-200",paddingTop:"size-100",paddingBottom:"size-100",borderTopColor:"light",borderTopWidth:"thin",children:h(ge,{direction:"row",justifyContent:"end",children:h(At,{variant:"danger",onClick:()=>{c(),o(null)},children:"Delete Dataset"})})})]}))},[c,n]);return B("div",{onClick:g=>{g.preventDefault(),g.stopPropagation()},children:[h(Gc,{align:"end",buttonSize:"compact",isDisabled:s,onAction:g=>{switch(g){case"deleteDataset":u();break}},children:h(Ht,{children:B(ge,{direction:"row",gap:"size-75",justifyContent:"start",alignItems:"center",children:[h(ke,{svg:h(Pe.TrashOutline,{})}),h(me,{children:"Delete"})]})},"deleteDataset")}),h(Fn,{type:"modal",isDismissable:!0,onDismiss:()=>o(null),children:a})]})}var hat=100;function cGn(t){let e=t.id;if(e!=="createdAt"&&e!=="name")throw new Error("Invalid sort column");return{col:e,dir:t.desc?"desc":"asc"}}function Cat(t){let[e,n]=(0,cd.useState)([]),i=(0,cd.useRef)(null),r=Zn(),a=Zo(),o=dm(),{data:l,loadNext:s,hasNext:c,isLoadingNext:u,refetch:g}=(0,fat.usePaginationFragment)(dat,t.query),d=(0,cd.useMemo)(()=>l.datasets.edges.map(f=>f.node),[l]),b=cd.default.useCallback(f=>{if(f){let{scrollHeight:C,scrollTop:v,clientHeight:x}=f;C-v-x<300&&!u&&c&&s(hat)}},[c,u,s]),m=Gr({columns:[{header:"name",accessorKey:"name",cell:({row:f})=>{let v=f.original.experimentCount>0?`${f.original.id}/experiments`:`${f.original.id}/examples`;return h(_l,{to:v,children:f.original.name})}},{header:"description",accessorKey:"description",enableSorting:!1},{header:"created at",accessorKey:"createdAt",cell:sd},{header:"example count",accessorKey:"exampleCount",enableSorting:!1,meta:{textAlign:"right"}},{header:"experiment count",accessorKey:"experimentCount",enableSorting:!1,meta:{textAlign:"right"}},{header:"",id:"actions",enableSorting:!1,size:10,cell:({row:f})=>h(pat,{datasetId:f.original.id,datasetName:f.original.name,onDatasetDelete:()=>{a({title:"Dataset deleted",message:`${f.original.name} has been successfully deleted.`}),g({},{fetchPolicy:"store-and-network"})},onDatasetDeleteError:C=>{o({title:"Dataset deletion failed",message:C.message})}})}],data:d,state:{sorting:e},getCoreRowModel:Wr(),getSortedRowModel:Zg(),onSortingChange:n,manualSorting:!0});(0,cd.useEffect)(()=>{let f=e[0];(0,cd.startTransition)(()=>{g({sort:f?cGn(f):{col:"createdAt",dir:"desc"},after:null,first:hat},{fetchPolicy:"store-and-network"})})},[e,g]);let I=m.getRowModel().rows,p=I.length===0;return h("div",{css:$`
|
|
7754
7754
|
flex: 1 1 auto;
|
|
7755
7755
|
overflow: auto;
|
|
7756
7756
|
`,onScroll:f=>b(f.target),ref:i,children:B("table",{css:wg,children:[h("thead",{children:m.getHeaderGroups().map(f=>h("tr",{children:f.headers.map(C=>h("th",{colSpan:C.colSpan,children:C.isPlaceholder?null:B("div",{className:C.column.getCanSort()?"cursor-pointer":"",onClick:C.column.getToggleSortingHandler(),style:{textAlign:C.column.columnDef.meta?.textAlign},children:[Hn(C.column.columnDef.header,C.getContext()),C.column.getIsSorted()?h(ke,{className:"sort-icon",svg:C.column.getIsSorted()==="asc"?h(Pe.ArrowUpFilled,{}):h(Pe.ArrowDownFilled,{})}):null]})},C.id))},f.id))}),p?h(Ul,{}):h("tbody",{children:I.map(f=>h("tr",{onClick:()=>{let v=f.original.experimentCount>0?`${f.original.id}/experiments`:`${f.original.id}/examples`;r(v)},children:f.getVisibleCells().map(C=>h("td",{align:C.column.columnDef.meta?.textAlign,children:Hn(C.column.columnDef.cell,C.getContext())},C.id))},f.id))})]})})}function yat(){return h(K0.Suspense,{fallback:h(Qr,{}),children:h(uGn,{})})}function uGn(){let[t,e]=(0,K0.useState)(0),n=(0,Aat.useLazyLoadQuery)(oat,{},{fetchKey:t}),i=(0,K0.useCallback)(()=>{e(r=>r+1)},[e]);return B(ge,{direction:"column",height:"100%",children:[h(De,{padding:"size-200",borderBottomWidth:"thin",borderBottomColor:"dark",flex:"none",children:B(ge,{direction:"row",justifyContent:"space-between",children:[h(dn,{level:1,children:"Datasets"}),h(gGn,{onDatasetCreated:i})]})}),h(Cat,{query:n})]})}function gGn({onDatasetCreated:t}){let e=Zn(),n=Zo(),i=dm(),[r,a]=(0,K0.useState)(null),o=()=>{a(h(Mn,{size:"S",title:"New Dataset",children:h(rY,{onDatasetCreated:s=>{n({title:"Dataset created",message:`${s.name} has been successfully created.`,action:{text:"Go to Dataset",onClick:()=>{e(`/datasets/${s.id}`)}}}),a(null),t()},onDatasetCreateError:s=>{i({title:"Dataset creation failed",message:s.message})}})}))},l=()=>{a(h(Mn,{size:"M",title:"New Dataset from CSV",children:h(lat,{onDatasetCreated:s=>{n({title:"Dataset created",message:`${s.name} has been successfully created.`,action:{text:"Go to Dataset",onClick:()=>{e(`/datasets/${s.id}`)}}}),a(null),t()},onDatasetCreateError:s=>{i({title:"Dataset creation failed",message:s.message})}})}))};return B($t,{children:[B(Gc,{buttonText:"Create Dataset",align:"end",icon:h(ke,{svg:h(Pe.DatabaseOutline,{})}),onAction:s=>{switch(s){case"newDataset":o();break;case"datasetFromCSV":l();break}},children:[h(Ht,{children:"New Dataset"},"newDataset"),h(Ht,{children:"Dataset from CSV"},"datasetFromCSV")]}),h(Fn,{type:"modal",isDismissable:!0,onDismiss:()=>a(null),children:r})]})}var tA=P(ie());var uY=P(ie());var vat=function(){var t=[{defaultValue:null,kind:"LocalArgument",name:"datasetId"}],e=[{kind:"Variable",name:"id",variableName:"datasetId"}],n={alias:null,args:null,kind:"ScalarField",name:"id",storageKey:null},i={kind:"InlineFragment",selections:[{alias:"latestVersions",args:[{kind:"Literal",name:"first",value:1},{kind:"Literal",name:"sort",value:{col:"createdAt",dir:"desc"}}],concreteType:"DatasetVersionConnection",kind:"LinkedField",name:"versions",plural:!1,selections:[{alias:null,args:null,concreteType:"DatasetVersionEdge",kind:"LinkedField",name:"edges",plural:!0,selections:[{alias:"version",args:null,concreteType:"DatasetVersion",kind:"LinkedField",name:"node",plural:!1,selections:[n,{alias:null,args:null,kind:"ScalarField",name:"description",storageKey:null},{alias:null,args:null,kind:"ScalarField",name:"createdAt",storageKey:null}],storageKey:null}],storageKey:null}],storageKey:'versions(first:1,sort:{"col":"createdAt","dir":"desc"})'}],type:"Dataset",abstractKey:null};return{fragment:{argumentDefinitions:t,kind:"Fragment",metadata:null,name:"datasetStore_latestVersionQuery",selections:[{alias:"dataset",args:e,concreteType:null,kind:"LinkedField",name:"node",plural:!1,selections:[n,i],storageKey:null}],type:"Query",abstractKey:null},kind:"Request",operation:{argumentDefinitions:t,kind:"Operation",name:"datasetStore_latestVersionQuery",selections:[{alias:"dataset",args:e,concreteType:null,kind:"LinkedField",name:"node",plural:!1,selections:[{alias:null,args:null,kind:"ScalarField",name:"__typename",storageKey:null},n,i],storageKey:null}]},params:{cacheID:"d7075240e4dae8871997e57616c05302",id:null,metadata:{},name:"datasetStore_latestVersionQuery",operationKind:"query",text:`query datasetStore_latestVersionQuery(
|
|
@@ -8152,7 +8152,7 @@ fragment ExperimentsTableFragment on Dataset {
|
|
|
8152
8152
|
__typename
|
|
8153
8153
|
}
|
|
8154
8154
|
}
|
|
8155
|
-
`}}}();Vot.hash="4ab310746eb51c6a3fcb799d2c972762";var Eot=Vot;var a3=P(ie()),Jot=P(wt());function Hot(t){let e=Zn(),[n,i]=(0,a3.useState)(null),[r,a]=(0,Jot.useMutation)(Eot),{datasetId:o,selectedExperiments:l,onClearSelection:s,onExperimentsDeleted:c}=t,u=l.length!==1,g=Zo(),d=dm(),b=(0,a3.useCallback)(()=>{r({variables:{input:{experimentIds:l.map(I=>I.id)}},onCompleted:()=>{g({title:"Examples Deleted",message:`${l.length} experiment${u?"s":""} have been deleted.`}),c(),s()},onError:I=>{d({title:"An error occurred",message:`Failed to delete examples: ${I.message}`})}})},[r,u,d,g,s,c,l]),m=(0,a3.useCallback)(()=>{i(B(Mn,{size:"S",title:"Delete Experiments",children:[h(De,{padding:"size-200",children:h(me,{color:"danger",children:"Are you sure you want to delete these experiments? This cannot be undone."})}),h(De,{paddingEnd:"size-200",paddingTop:"size-100",paddingBottom:"size-100",borderTopColor:"light",borderTopWidth:"thin",children:h(ge,{direction:"row",justifyContent:"end",children:h(At,{variant:"danger",onClick:()=>{b(),i(null)},children:"Delete Experiments"})})})]}))},[b]);return B("div",{css:$`
|
|
8155
|
+
`}}}();Vot.hash="4ab310746eb51c6a3fcb799d2c972762";var Eot=Vot;var a3=P(ie()),Jot=P(wt());function Hot(t){let e=Zn(),[n,i]=(0,a3.useState)(null),[r,a]=(0,Jot.useMutation)(Eot),{datasetId:o,selectedExperiments:l,onClearSelection:s,onExperimentsDeleted:c}=t,u=l.length!==1,g=Zo(),d=dm(),b=(0,a3.useCallback)(()=>{r({variables:{input:{experimentIds:l.map(I=>I.id)}},onCompleted:()=>{g({title:"Examples Deleted",message:`${l.length} experiment${u?"s":""} have been deleted.`}),c(),s()},onError:I=>{d({title:"An error occurred",message:`Failed to delete examples: ${I.message}`})}})},[r,u,d,g,s,c,l]),m=(0,a3.useCallback)(()=>{i(B(Mn,{size:"S",title:"Delete Experiments",children:[h(De,{padding:"size-200",children:h(me,{color:"danger",children:"Are you sure you want to delete these experiments? This will also delete all associated annotations and traces, and it cannot be undone."})}),h(De,{paddingEnd:"size-200",paddingTop:"size-100",paddingBottom:"size-100",borderTopColor:"light",borderTopWidth:"thin",children:h(ge,{direction:"row",justifyContent:"end",children:h(At,{variant:"danger",onClick:()=>{b(),i(null)},children:"Delete Experiments"})})})]}))},[b]);return B("div",{css:$`
|
|
8156
8156
|
position: absolute;
|
|
8157
8157
|
bottom: var(--ac-global-dimension-size-400);
|
|
8158
8158
|
left: 50%;
|
phoenix/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "4.
|
|
1
|
+
__version__ = "4.8.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|