arize-phoenix 12.5.0__py3-none-any.whl → 12.6.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-12.5.0.dist-info → arize_phoenix-12.6.0.dist-info}/METADATA +1 -1
- {arize_phoenix-12.5.0.dist-info → arize_phoenix-12.6.0.dist-info}/RECORD +19 -18
- phoenix/server/api/input_types/ExperimentRunSort.py +237 -0
- phoenix/server/api/types/Experiment.py +60 -25
- phoenix/server/static/.vite/manifest.json +44 -44
- phoenix/server/static/assets/{components-cwdYEs7B.js → components-CboqzKQ9.js} +353 -337
- phoenix/server/static/assets/{index-Dc0vD1Rn.js → index-CYYGI5-x.js} +2 -2
- phoenix/server/static/assets/{pages-BDkB3a_a.js → pages-DdlUeKi2.js} +545 -577
- phoenix/server/static/assets/vendor-CQ4tN9P7.js +918 -0
- phoenix/server/static/assets/vendor-arizeai-Cb1ncvYH.js +106 -0
- phoenix/server/static/assets/{vendor-codemirror-Bv8J_7an.js → vendor-codemirror-CckmKopH.js} +3 -3
- phoenix/server/static/assets/{vendor-recharts-DcLgzI7g.js → vendor-recharts-BC1ysIKu.js} +1 -1
- phoenix/server/static/assets/{vendor-shiki-BF8rh_7m.js → vendor-shiki-B45T-YxN.js} +1 -1
- phoenix/server/static/assets/vendor-three-BtCyLs1w.js +3840 -0
- phoenix/version.py +1 -1
- phoenix/server/static/assets/vendor-Ce6GTAin.js +0 -914
- phoenix/server/static/assets/vendor-arizeai-CSF-1Kc5.js +0 -156
- phoenix/server/static/assets/vendor-three-BLWp5bic.js +0 -2998
- {arize_phoenix-12.5.0.dist-info → arize_phoenix-12.6.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-12.5.0.dist-info → arize_phoenix-12.6.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-12.5.0.dist-info → arize_phoenix-12.6.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-12.5.0.dist-info → arize_phoenix-12.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
7
|
phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
|
|
8
8
|
phoenix/settings.py,sha256=2kHfT3BNOVd4dAO1bq-syEQbHSG8oX2-7NhOwK2QREk,896
|
|
9
|
-
phoenix/version.py,sha256=
|
|
9
|
+
phoenix/version.py,sha256=oxSKCFLBjhFlgZSaA2j_3urrHMkITGfFWBcpgSrk6mo,23
|
|
10
10
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
12
12
|
phoenix/core/model.py,sha256=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
|
|
@@ -234,6 +234,7 @@ phoenix/server/api/input_types/DeleteDatasetInput.py,sha256=p7xjCyWnVCIXHnezmDiW
|
|
|
234
234
|
phoenix/server/api/input_types/DeleteExperimentsInput.py,sha256=4d9N0vSLYbuysAamGoPUP_m8vdVhwrZmXoi2vhy_HdI,141
|
|
235
235
|
phoenix/server/api/input_types/DimensionFilter.py,sha256=eBYcn7ECSJQlEePvbStqkHBRicbIL4vEAzFJwX7bacQ,3137
|
|
236
236
|
phoenix/server/api/input_types/DimensionInput.py,sha256=Vfx5FmiMKey4-EHDQsQRPzSAMRJMN5oVMLDUl4NKAa8,164
|
|
237
|
+
phoenix/server/api/input_types/ExperimentRunSort.py,sha256=3E7ucBdJCoC7u3tIKyqDxSorphUwPXDLPYFL_VJUvjs,8679
|
|
237
238
|
phoenix/server/api/input_types/GenerativeCredentialInput.py,sha256=sEM9UtgDMMuhImLwGXctD8BWDs2V3hNQ1mosoklRZvc,219
|
|
238
239
|
phoenix/server/api/input_types/GenerativeModelInput.py,sha256=M9R5LmLjyxOYPEIiann4ln23degOWJ2GTIk64bi73yI,841
|
|
239
240
|
phoenix/server/api/input_types/Granularity.py,sha256=dbBlD_GsIBa8_xrx4JlLuR59bQ0NRB5H-cv1zvcb-cw,2299
|
|
@@ -337,7 +338,7 @@ phoenix/server/api/types/EvaluationSummary.py,sha256=vILYejnfPvMwWEXOwhQZsANvYe3
|
|
|
337
338
|
phoenix/server/api/types/Event.py,sha256=iYt_Jx1Roioo0vZ0iPeJTHcTu6NSm4ilVMJ-IMUHAKk,3970
|
|
338
339
|
phoenix/server/api/types/EventMetadata.py,sha256=-J0tYF9eZTHwCjwxQHY7Gckr2_MNW5OoWT1mydweZNM,635
|
|
339
340
|
phoenix/server/api/types/ExampleRevisionInterface.py,sha256=gV3Gt9-3Oi5wjaVtepC6nOt3FzTzZFD1KebNnqiw56E,294
|
|
340
|
-
phoenix/server/api/types/Experiment.py,sha256=
|
|
341
|
+
phoenix/server/api/types/Experiment.py,sha256=ogE0Ks6MPIc5zeA77iyGNv5Y1pz_-NM1GU_de7-QSq8,9532
|
|
341
342
|
phoenix/server/api/types/ExperimentAnnotationSummary.py,sha256=Uk3JtxIrsMoZT5tqc4nJdUOM3XegVzjUyoV3pkjNotE,256
|
|
342
343
|
phoenix/server/api/types/ExperimentComparison.py,sha256=fj4KoAPFNJvfrHBMloGkHz_-7Lf403IMe0OwDDJyZWk,383
|
|
343
344
|
phoenix/server/api/types/ExperimentRepeatedRunGroup.py,sha256=a2-C6ZWyFm-THvus6n4WDYGtmapm-ZWFaDahW7A2i28,5434
|
|
@@ -429,17 +430,17 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
429
430
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
430
431
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
431
432
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
432
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
433
|
-
phoenix/server/static/assets/components-
|
|
434
|
-
phoenix/server/static/assets/index-
|
|
435
|
-
phoenix/server/static/assets/pages-
|
|
433
|
+
phoenix/server/static/.vite/manifest.json,sha256=5fpY6vVAsxBRbIz1baNZ1Jd0FZIXJJ5bZq3sORv9VtU,2328
|
|
434
|
+
phoenix/server/static/assets/components-CboqzKQ9.js,sha256=BMU19yw43gTzg0-RbLXhP_xgOifcxpNKF3Ff0k1PiDE,743011
|
|
435
|
+
phoenix/server/static/assets/index-CYYGI5-x.js,sha256=lz6Y3i3pwdaFw2QfYqp7gaVgmWYafoUWvvu1A7ciCMg,63675
|
|
436
|
+
phoenix/server/static/assets/pages-DdlUeKi2.js,sha256=YUVU8xR7I9j927Sptk3AkiXC7SgIcaDTfAIJl3OSdKE,1352219
|
|
436
437
|
phoenix/server/static/assets/vendor-BGzfc4EU.css,sha256=Nx5Lmx-bqYR7nsO_O4kEBcrJ8cwknWjZ6seHN3_s4UQ,3171
|
|
437
|
-
phoenix/server/static/assets/vendor-
|
|
438
|
-
phoenix/server/static/assets/vendor-arizeai-
|
|
439
|
-
phoenix/server/static/assets/vendor-codemirror-
|
|
440
|
-
phoenix/server/static/assets/vendor-recharts-
|
|
441
|
-
phoenix/server/static/assets/vendor-shiki-
|
|
442
|
-
phoenix/server/static/assets/vendor-three-
|
|
438
|
+
phoenix/server/static/assets/vendor-CQ4tN9P7.js,sha256=T-jwFQyaPcs9NTsr1-LgZyTCOHuU79yNocsMVZpL9os,2647461
|
|
439
|
+
phoenix/server/static/assets/vendor-arizeai-Cb1ncvYH.js,sha256=SEQFDzn04e85NQ20oEHzQUtkhBghcT_ihBRr3PCX2_4,61555
|
|
440
|
+
phoenix/server/static/assets/vendor-codemirror-CckmKopH.js,sha256=MQyNw9XiM5yirfH35t-lnEh07dgg29PdGhy4iUiv9vA,413211
|
|
441
|
+
phoenix/server/static/assets/vendor-recharts-BC1ysIKu.js,sha256=D38l2FL3n4q-emg9NWzdIhye8tleaur0d9Qu-lMXgIE,231652
|
|
442
|
+
phoenix/server/static/assets/vendor-shiki-B45T-YxN.js,sha256=EaUAfs0m0Gy_vwpnvWRTZQpiSIHxcmaY6tk_ASmiPPQ,305160
|
|
443
|
+
phoenix/server/static/assets/vendor-three-BtCyLs1w.js,sha256=E6e1HbskKn61fWQPWmiZiPXXGHfZYn-30v0nofpDaqo,704132
|
|
443
444
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
444
445
|
phoenix/server/templates/index.html,sha256=_iKIyXEDDr5cTTnrUCjCd617U6Alc1k-IXtdKSt8g14,7215
|
|
445
446
|
phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -478,9 +479,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
|
|
|
478
479
|
phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
|
|
479
480
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
480
481
|
phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
|
|
481
|
-
arize_phoenix-12.
|
|
482
|
-
arize_phoenix-12.
|
|
483
|
-
arize_phoenix-12.
|
|
484
|
-
arize_phoenix-12.
|
|
485
|
-
arize_phoenix-12.
|
|
486
|
-
arize_phoenix-12.
|
|
482
|
+
arize_phoenix-12.6.0.dist-info/METADATA,sha256=8sMWL54La0PXr6Qh0N6-DY-hTJL-FYanll5qitmNa90,34069
|
|
483
|
+
arize_phoenix-12.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
484
|
+
arize_phoenix-12.6.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
|
|
485
|
+
arize_phoenix-12.6.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
486
|
+
arize_phoenix-12.6.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
487
|
+
arize_phoenix-12.6.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import operator
|
|
2
|
+
from enum import Enum, auto
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
import strawberry
|
|
6
|
+
from sqlalchemy import ColumnElement, Select, and_, func, literal, or_, select, tuple_
|
|
7
|
+
from sqlalchemy.sql.selectable import NamedFromClause
|
|
8
|
+
from strawberry import Maybe
|
|
9
|
+
from typing_extensions import assert_never
|
|
10
|
+
|
|
11
|
+
from phoenix.db import models
|
|
12
|
+
from phoenix.server.api.types.pagination import (
|
|
13
|
+
Cursor,
|
|
14
|
+
CursorSortColumn,
|
|
15
|
+
CursorSortColumnDataType,
|
|
16
|
+
CursorSortColumnValue,
|
|
17
|
+
)
|
|
18
|
+
from phoenix.server.api.types.SortDir import SortDir
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@strawberry.enum
|
|
22
|
+
class ExperimentRunMetric(Enum):
|
|
23
|
+
latencyMs = auto()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@strawberry.input(one_of=True)
|
|
27
|
+
class ExperimentRunColumn:
|
|
28
|
+
metric: Maybe[ExperimentRunMetric]
|
|
29
|
+
annotation_name: Maybe[str]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@strawberry.input(description="The sort key and direction for experiment run connections")
|
|
33
|
+
class ExperimentRunSort:
|
|
34
|
+
col: ExperimentRunColumn
|
|
35
|
+
dir: SortDir
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_experiment_run_cursor(
|
|
39
|
+
run: models.ExperimentRun, annotation_score: Optional[float], sort: Optional[ExperimentRunSort]
|
|
40
|
+
) -> Cursor:
|
|
41
|
+
sort_column: Optional[CursorSortColumn] = None
|
|
42
|
+
if sort:
|
|
43
|
+
if sort.col.metric:
|
|
44
|
+
metric = sort.col.metric.value
|
|
45
|
+
assert metric is not None
|
|
46
|
+
if metric is ExperimentRunMetric.latencyMs:
|
|
47
|
+
sort_column = CursorSortColumn(
|
|
48
|
+
type=CursorSortColumnDataType.FLOAT,
|
|
49
|
+
value=run.latency_ms,
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
assert_never(metric)
|
|
53
|
+
elif sort.col.annotation_name:
|
|
54
|
+
data_type = (
|
|
55
|
+
CursorSortColumnDataType.FLOAT
|
|
56
|
+
if annotation_score is not None
|
|
57
|
+
else CursorSortColumnDataType.NULL
|
|
58
|
+
)
|
|
59
|
+
sort_column = CursorSortColumn(
|
|
60
|
+
type=data_type,
|
|
61
|
+
value=annotation_score,
|
|
62
|
+
)
|
|
63
|
+
return Cursor(rowid=run.id, sort_column=sort_column)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def add_order_by_and_page_start_to_query(
|
|
67
|
+
query: Select[Any],
|
|
68
|
+
sort: Optional[ExperimentRunSort],
|
|
69
|
+
experiment_rowid: int,
|
|
70
|
+
after_experiment_run_rowid: Optional[int],
|
|
71
|
+
after_sort_column_value: Optional[CursorSortColumnValue] = None,
|
|
72
|
+
) -> Select[Any]:
|
|
73
|
+
mean_annotation_scores: Optional[NamedFromClause] = None
|
|
74
|
+
if sort and sort.col.annotation_name:
|
|
75
|
+
annotation_name = sort.col.annotation_name.value
|
|
76
|
+
assert annotation_name is not None
|
|
77
|
+
mean_annotation_scores = _get_mean_annotation_scores_subquery(annotation_name)
|
|
78
|
+
order_by_columns = _get_order_by_columns(
|
|
79
|
+
sort=sort, experiment_rowid=experiment_rowid, mean_annotation_scores=mean_annotation_scores
|
|
80
|
+
)
|
|
81
|
+
query = query.order_by(*order_by_columns)
|
|
82
|
+
if after_experiment_run_rowid is not None:
|
|
83
|
+
query = _add_after_expression(
|
|
84
|
+
query=query,
|
|
85
|
+
sort=sort,
|
|
86
|
+
experiment_run_rowid=after_experiment_run_rowid,
|
|
87
|
+
after_sort_column_value=after_sort_column_value,
|
|
88
|
+
mean_annotation_scores=mean_annotation_scores,
|
|
89
|
+
)
|
|
90
|
+
query = _add_joins_and_selects_to_query(
|
|
91
|
+
query=query,
|
|
92
|
+
sort=sort,
|
|
93
|
+
mean_annotation_scores=mean_annotation_scores,
|
|
94
|
+
)
|
|
95
|
+
return query
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _get_order_by_columns(
|
|
99
|
+
sort: Optional[ExperimentRunSort],
|
|
100
|
+
experiment_rowid: int,
|
|
101
|
+
mean_annotation_scores: Optional[NamedFromClause],
|
|
102
|
+
) -> tuple[ColumnElement[Any], ...]:
|
|
103
|
+
if not sort:
|
|
104
|
+
# Ideally, this would sort the runs by (example_id, repetition_number),
|
|
105
|
+
# but this would require making the cursor more complex or adding an additional query
|
|
106
|
+
# to handle the after cursor.
|
|
107
|
+
return (models.ExperimentRun.id.asc(),)
|
|
108
|
+
sort_direction = sort.dir
|
|
109
|
+
if sort.col.metric:
|
|
110
|
+
metric = sort.col.metric.value
|
|
111
|
+
assert metric is not None
|
|
112
|
+
if metric is ExperimentRunMetric.latencyMs:
|
|
113
|
+
if sort_direction is SortDir.asc:
|
|
114
|
+
return (models.ExperimentRun.latency_ms.asc(), models.ExperimentRun.id.asc())
|
|
115
|
+
else:
|
|
116
|
+
return (models.ExperimentRun.latency_ms.desc(), models.ExperimentRun.id.desc())
|
|
117
|
+
else:
|
|
118
|
+
assert_never(metric)
|
|
119
|
+
elif sort.col.annotation_name:
|
|
120
|
+
annotation_name = sort.col.annotation_name.value
|
|
121
|
+
assert annotation_name is not None
|
|
122
|
+
assert mean_annotation_scores is not None
|
|
123
|
+
if sort_direction is SortDir.asc:
|
|
124
|
+
return (
|
|
125
|
+
mean_annotation_scores.c.score.asc().nulls_last(),
|
|
126
|
+
models.ExperimentRun.id.asc(),
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
return (
|
|
130
|
+
mean_annotation_scores.c.score.desc().nulls_last(),
|
|
131
|
+
models.ExperimentRun.id.desc(),
|
|
132
|
+
)
|
|
133
|
+
raise NotImplementedError
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _add_after_expression(
|
|
137
|
+
query: Select[Any],
|
|
138
|
+
sort: Optional[ExperimentRunSort],
|
|
139
|
+
experiment_run_rowid: int,
|
|
140
|
+
after_sort_column_value: Optional[CursorSortColumnValue],
|
|
141
|
+
mean_annotation_scores: Optional[NamedFromClause],
|
|
142
|
+
) -> Select[Any]:
|
|
143
|
+
if not sort:
|
|
144
|
+
# Ideally, this would return the runs sorted by (example_id, repetition_number),
|
|
145
|
+
# but this would require making the cursor more complex or adding an additional query.
|
|
146
|
+
return query.where(models.ExperimentRun.id > literal(experiment_run_rowid))
|
|
147
|
+
sort_direction = sort.dir
|
|
148
|
+
compare_fn = operator.gt if sort_direction is SortDir.asc else operator.lt
|
|
149
|
+
if sort.col.metric:
|
|
150
|
+
metric = sort.col.metric.value
|
|
151
|
+
assert metric is not None
|
|
152
|
+
if metric is ExperimentRunMetric.latencyMs:
|
|
153
|
+
assert after_sort_column_value is not None
|
|
154
|
+
return query.where(
|
|
155
|
+
compare_fn(
|
|
156
|
+
tuple_(models.ExperimentRun.latency_ms, models.ExperimentRun.id),
|
|
157
|
+
tuple_(
|
|
158
|
+
literal(after_sort_column_value),
|
|
159
|
+
literal(experiment_run_rowid),
|
|
160
|
+
),
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
else:
|
|
164
|
+
assert_never(metric)
|
|
165
|
+
elif sort.col.annotation_name:
|
|
166
|
+
annotation_name = sort.col.annotation_name.value
|
|
167
|
+
assert annotation_name is not None
|
|
168
|
+
assert mean_annotation_scores is not None
|
|
169
|
+
if after_sort_column_value is None:
|
|
170
|
+
return query.where(
|
|
171
|
+
and_(
|
|
172
|
+
compare_fn(models.ExperimentRun.id, literal(experiment_run_rowid)),
|
|
173
|
+
mean_annotation_scores.c.score.is_(None),
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
return query.where(
|
|
178
|
+
or_(
|
|
179
|
+
compare_fn(
|
|
180
|
+
tuple_(mean_annotation_scores.c.score, models.ExperimentRun.id),
|
|
181
|
+
tuple_(
|
|
182
|
+
literal(after_sort_column_value),
|
|
183
|
+
literal(experiment_run_rowid),
|
|
184
|
+
),
|
|
185
|
+
),
|
|
186
|
+
mean_annotation_scores.c.score.is_(None),
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
raise NotImplementedError
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _get_mean_annotation_scores_subquery(annotation_name: str) -> NamedFromClause:
|
|
193
|
+
return (
|
|
194
|
+
select(
|
|
195
|
+
func.avg(models.ExperimentRunAnnotation.score).label("score"),
|
|
196
|
+
models.ExperimentRunAnnotation.experiment_run_id.label("experiment_run_id"),
|
|
197
|
+
)
|
|
198
|
+
.select_from(models.ExperimentRunAnnotation)
|
|
199
|
+
.join(
|
|
200
|
+
models.ExperimentRun,
|
|
201
|
+
models.ExperimentRunAnnotation.experiment_run_id == models.ExperimentRun.id,
|
|
202
|
+
)
|
|
203
|
+
.where(models.ExperimentRunAnnotation.name == annotation_name)
|
|
204
|
+
.group_by(models.ExperimentRunAnnotation.experiment_run_id)
|
|
205
|
+
.subquery()
|
|
206
|
+
.alias("mean_annotation_scores")
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _add_joins_and_selects_to_query(
|
|
211
|
+
query: Select[tuple[models.ExperimentRun]],
|
|
212
|
+
sort: Optional[ExperimentRunSort],
|
|
213
|
+
mean_annotation_scores: Optional[NamedFromClause],
|
|
214
|
+
) -> Select[tuple[models.ExperimentRun]]:
|
|
215
|
+
if not sort:
|
|
216
|
+
return query
|
|
217
|
+
if sort.col.metric:
|
|
218
|
+
metric = sort.col.metric.value
|
|
219
|
+
assert metric is not None
|
|
220
|
+
if metric is ExperimentRunMetric.latencyMs:
|
|
221
|
+
return query
|
|
222
|
+
else:
|
|
223
|
+
assert_never(metric)
|
|
224
|
+
elif sort.col.annotation_name:
|
|
225
|
+
annotation_name = sort.col.annotation_name.value
|
|
226
|
+
assert annotation_name is not None
|
|
227
|
+
assert mean_annotation_scores is not None
|
|
228
|
+
query = query.join(
|
|
229
|
+
mean_annotation_scores,
|
|
230
|
+
mean_annotation_scores.c.experiment_run_id == models.ExperimentRun.id,
|
|
231
|
+
isouter=True,
|
|
232
|
+
)
|
|
233
|
+
query = query.add_columns(
|
|
234
|
+
mean_annotation_scores.c.score.label("score")
|
|
235
|
+
) # the score must be in the select so that the value can be included in the cursor
|
|
236
|
+
return query
|
|
237
|
+
raise NotImplementedError
|
|
@@ -11,19 +11,27 @@ from strawberry.types import Info
|
|
|
11
11
|
|
|
12
12
|
from phoenix.db import models
|
|
13
13
|
from phoenix.server.api.context import Context
|
|
14
|
+
from phoenix.server.api.exceptions import BadRequest
|
|
15
|
+
from phoenix.server.api.input_types.ExperimentRunSort import (
|
|
16
|
+
ExperimentRunSort,
|
|
17
|
+
add_order_by_and_page_start_to_query,
|
|
18
|
+
get_experiment_run_cursor,
|
|
19
|
+
)
|
|
14
20
|
from phoenix.server.api.types.CostBreakdown import CostBreakdown
|
|
15
21
|
from phoenix.server.api.types.DatasetVersion import DatasetVersion
|
|
16
22
|
from phoenix.server.api.types.ExperimentAnnotationSummary import ExperimentAnnotationSummary
|
|
17
23
|
from phoenix.server.api.types.ExperimentRun import ExperimentRun, to_gql_experiment_run
|
|
18
24
|
from phoenix.server.api.types.pagination import (
|
|
19
|
-
|
|
25
|
+
Cursor,
|
|
20
26
|
CursorString,
|
|
21
|
-
|
|
27
|
+
connection_from_cursors_and_nodes,
|
|
22
28
|
)
|
|
23
29
|
from phoenix.server.api.types.Project import Project
|
|
24
30
|
from phoenix.server.api.types.SpanCostDetailSummaryEntry import SpanCostDetailSummaryEntry
|
|
25
31
|
from phoenix.server.api.types.SpanCostSummary import SpanCostSummary
|
|
26
32
|
|
|
33
|
+
_DEFAULT_EXPERIMENT_RUNS_PAGE_SIZE = 50
|
|
34
|
+
|
|
27
35
|
|
|
28
36
|
@strawberry.type
|
|
29
37
|
class Experiment(Node):
|
|
@@ -57,33 +65,60 @@ class Experiment(Node):
|
|
|
57
65
|
async def runs(
|
|
58
66
|
self,
|
|
59
67
|
info: Info[Context, None],
|
|
60
|
-
first: Optional[int] =
|
|
61
|
-
last: Optional[int] = UNSET,
|
|
68
|
+
first: Optional[int] = _DEFAULT_EXPERIMENT_RUNS_PAGE_SIZE,
|
|
62
69
|
after: Optional[CursorString] = UNSET,
|
|
63
|
-
|
|
70
|
+
sort: Optional[ExperimentRunSort] = UNSET,
|
|
64
71
|
) -> Connection[ExperimentRun]:
|
|
65
|
-
|
|
66
|
-
first
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
if first is not None and first <= 0:
|
|
73
|
+
raise BadRequest("first must be a positive integer if set")
|
|
74
|
+
experiment_rowid = self.id_attr
|
|
75
|
+
page_size = first or _DEFAULT_EXPERIMENT_RUNS_PAGE_SIZE
|
|
76
|
+
experiment_runs_query = (
|
|
77
|
+
select(models.ExperimentRun)
|
|
78
|
+
.where(models.ExperimentRun.experiment_id == experiment_rowid)
|
|
79
|
+
.options(joinedload(models.ExperimentRun.trace).load_only(models.Trace.trace_id))
|
|
80
|
+
.limit(page_size + 1)
|
|
70
81
|
)
|
|
71
|
-
|
|
82
|
+
|
|
83
|
+
after_experiment_run_rowid = None
|
|
84
|
+
after_sort_column_value = None
|
|
85
|
+
if after:
|
|
86
|
+
cursor = Cursor.from_string(after)
|
|
87
|
+
after_experiment_run_rowid = cursor.rowid
|
|
88
|
+
if cursor.sort_column is not None:
|
|
89
|
+
after_sort_column_value = cursor.sort_column.value
|
|
90
|
+
|
|
91
|
+
experiment_runs_query = add_order_by_and_page_start_to_query(
|
|
92
|
+
query=experiment_runs_query,
|
|
93
|
+
sort=sort,
|
|
94
|
+
experiment_rowid=experiment_rowid,
|
|
95
|
+
after_experiment_run_rowid=after_experiment_run_rowid,
|
|
96
|
+
after_sort_column_value=after_sort_column_value,
|
|
97
|
+
)
|
|
98
|
+
|
|
72
99
|
async with info.context.db() as session:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
results = (await session.execute(experiment_runs_query)).all()
|
|
101
|
+
|
|
102
|
+
has_next_page = False
|
|
103
|
+
if len(results) > page_size:
|
|
104
|
+
results = results[:page_size]
|
|
105
|
+
has_next_page = True
|
|
106
|
+
|
|
107
|
+
cursors_and_nodes = []
|
|
108
|
+
for result in results:
|
|
109
|
+
run = result[0]
|
|
110
|
+
annotation_score = result[1] if len(result) > 1 else None
|
|
111
|
+
gql_run = to_gql_experiment_run(run)
|
|
112
|
+
cursor = get_experiment_run_cursor(
|
|
113
|
+
run=run, annotation_score=annotation_score, sort=sort
|
|
114
|
+
)
|
|
115
|
+
cursors_and_nodes.append((cursor, gql_run))
|
|
116
|
+
|
|
117
|
+
return connection_from_cursors_and_nodes(
|
|
118
|
+
cursors_and_nodes=cursors_and_nodes,
|
|
119
|
+
has_previous_page=False, # set to false since we are only doing forward pagination (https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo.Fields) # noqa: E501
|
|
120
|
+
has_next_page=has_next_page,
|
|
121
|
+
)
|
|
87
122
|
|
|
88
123
|
@strawberry.field
|
|
89
124
|
async def run_count(self, info: Info[Context, None]) -> int:
|
|
@@ -1,93 +1,93 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_components-
|
|
3
|
-
"file": "assets/components-
|
|
2
|
+
"_components-CboqzKQ9.js": {
|
|
3
|
+
"file": "assets/components-CboqzKQ9.js",
|
|
4
4
|
"name": "components",
|
|
5
5
|
"imports": [
|
|
6
|
-
"_vendor-
|
|
7
|
-
"_pages-
|
|
8
|
-
"_vendor-arizeai-
|
|
9
|
-
"_vendor-codemirror-
|
|
10
|
-
"_vendor-three-
|
|
6
|
+
"_vendor-CQ4tN9P7.js",
|
|
7
|
+
"_pages-DdlUeKi2.js",
|
|
8
|
+
"_vendor-arizeai-Cb1ncvYH.js",
|
|
9
|
+
"_vendor-codemirror-CckmKopH.js",
|
|
10
|
+
"_vendor-three-BtCyLs1w.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
|
-
"_pages-
|
|
14
|
-
"file": "assets/pages-
|
|
13
|
+
"_pages-DdlUeKi2.js": {
|
|
14
|
+
"file": "assets/pages-DdlUeKi2.js",
|
|
15
15
|
"name": "pages",
|
|
16
16
|
"imports": [
|
|
17
|
-
"_vendor-
|
|
18
|
-
"_components-
|
|
19
|
-
"_vendor-arizeai-
|
|
20
|
-
"_vendor-codemirror-
|
|
21
|
-
"_vendor-recharts-
|
|
17
|
+
"_vendor-CQ4tN9P7.js",
|
|
18
|
+
"_components-CboqzKQ9.js",
|
|
19
|
+
"_vendor-arizeai-Cb1ncvYH.js",
|
|
20
|
+
"_vendor-codemirror-CckmKopH.js",
|
|
21
|
+
"_vendor-recharts-BC1ysIKu.js"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
24
|
"_vendor-BGzfc4EU.css": {
|
|
25
25
|
"file": "assets/vendor-BGzfc4EU.css",
|
|
26
26
|
"src": "_vendor-BGzfc4EU.css"
|
|
27
27
|
},
|
|
28
|
-
"_vendor-
|
|
29
|
-
"file": "assets/vendor-
|
|
28
|
+
"_vendor-CQ4tN9P7.js": {
|
|
29
|
+
"file": "assets/vendor-CQ4tN9P7.js",
|
|
30
30
|
"name": "vendor",
|
|
31
31
|
"imports": [
|
|
32
|
-
"_vendor-three-
|
|
32
|
+
"_vendor-three-BtCyLs1w.js"
|
|
33
33
|
],
|
|
34
34
|
"css": [
|
|
35
35
|
"assets/vendor-BGzfc4EU.css"
|
|
36
36
|
]
|
|
37
37
|
},
|
|
38
|
-
"_vendor-arizeai-
|
|
39
|
-
"file": "assets/vendor-arizeai-
|
|
38
|
+
"_vendor-arizeai-Cb1ncvYH.js": {
|
|
39
|
+
"file": "assets/vendor-arizeai-Cb1ncvYH.js",
|
|
40
40
|
"name": "vendor-arizeai",
|
|
41
41
|
"imports": [
|
|
42
|
-
"_vendor-
|
|
42
|
+
"_vendor-CQ4tN9P7.js"
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
|
-
"_vendor-codemirror-
|
|
46
|
-
"file": "assets/vendor-codemirror-
|
|
45
|
+
"_vendor-codemirror-CckmKopH.js": {
|
|
46
|
+
"file": "assets/vendor-codemirror-CckmKopH.js",
|
|
47
47
|
"name": "vendor-codemirror",
|
|
48
48
|
"imports": [
|
|
49
|
-
"_vendor-
|
|
50
|
-
"_vendor-shiki-
|
|
49
|
+
"_vendor-CQ4tN9P7.js",
|
|
50
|
+
"_vendor-shiki-B45T-YxN.js"
|
|
51
51
|
],
|
|
52
52
|
"dynamicImports": [
|
|
53
|
-
"_vendor-shiki-
|
|
54
|
-
"_vendor-shiki-
|
|
55
|
-
"_vendor-shiki-
|
|
53
|
+
"_vendor-shiki-B45T-YxN.js",
|
|
54
|
+
"_vendor-shiki-B45T-YxN.js",
|
|
55
|
+
"_vendor-shiki-B45T-YxN.js"
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
|
-
"_vendor-recharts-
|
|
59
|
-
"file": "assets/vendor-recharts-
|
|
58
|
+
"_vendor-recharts-BC1ysIKu.js": {
|
|
59
|
+
"file": "assets/vendor-recharts-BC1ysIKu.js",
|
|
60
60
|
"name": "vendor-recharts",
|
|
61
61
|
"imports": [
|
|
62
|
-
"_vendor-
|
|
62
|
+
"_vendor-CQ4tN9P7.js"
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
|
-
"_vendor-shiki-
|
|
66
|
-
"file": "assets/vendor-shiki-
|
|
65
|
+
"_vendor-shiki-B45T-YxN.js": {
|
|
66
|
+
"file": "assets/vendor-shiki-B45T-YxN.js",
|
|
67
67
|
"name": "vendor-shiki",
|
|
68
68
|
"isDynamicEntry": true,
|
|
69
69
|
"imports": [
|
|
70
|
-
"_vendor-
|
|
70
|
+
"_vendor-CQ4tN9P7.js"
|
|
71
71
|
]
|
|
72
72
|
},
|
|
73
|
-
"_vendor-three-
|
|
74
|
-
"file": "assets/vendor-three-
|
|
73
|
+
"_vendor-three-BtCyLs1w.js": {
|
|
74
|
+
"file": "assets/vendor-three-BtCyLs1w.js",
|
|
75
75
|
"name": "vendor-three"
|
|
76
76
|
},
|
|
77
77
|
"index.tsx": {
|
|
78
|
-
"file": "assets/index-
|
|
78
|
+
"file": "assets/index-CYYGI5-x.js",
|
|
79
79
|
"name": "index",
|
|
80
80
|
"src": "index.tsx",
|
|
81
81
|
"isEntry": true,
|
|
82
82
|
"imports": [
|
|
83
|
-
"_vendor-
|
|
84
|
-
"_vendor-arizeai-
|
|
85
|
-
"_pages-
|
|
86
|
-
"_components-
|
|
87
|
-
"_vendor-three-
|
|
88
|
-
"_vendor-codemirror-
|
|
89
|
-
"_vendor-shiki-
|
|
90
|
-
"_vendor-recharts-
|
|
83
|
+
"_vendor-CQ4tN9P7.js",
|
|
84
|
+
"_vendor-arizeai-Cb1ncvYH.js",
|
|
85
|
+
"_pages-DdlUeKi2.js",
|
|
86
|
+
"_components-CboqzKQ9.js",
|
|
87
|
+
"_vendor-three-BtCyLs1w.js",
|
|
88
|
+
"_vendor-codemirror-CckmKopH.js",
|
|
89
|
+
"_vendor-shiki-B45T-YxN.js",
|
|
90
|
+
"_vendor-recharts-BC1ysIKu.js"
|
|
91
91
|
]
|
|
92
92
|
}
|
|
93
93
|
}
|