arize-phoenix 8.4.0__py3-none-any.whl → 8.4.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.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-8.4.0.dist-info → arize_phoenix-8.4.1.dist-info}/METADATA +1 -1
- {arize_phoenix-8.4.0.dist-info → arize_phoenix-8.4.1.dist-info}/RECORD +15 -15
- phoenix/db/models.py +68 -2
- phoenix/server/api/dataloaders/span_descendants.py +71 -34
- phoenix/server/api/input_types/SpanSort.py +1 -1
- phoenix/server/api/types/Span.py +27 -4
- phoenix/server/static/.vite/manifest.json +9 -9
- phoenix/server/static/assets/{components-BgFPI6sn.js → components-CRlSj2mp.js} +1 -1
- phoenix/server/static/assets/{index-CIkk8uHr.js → index-YUNmSSFA.js} +1 -1
- phoenix/server/static/assets/{pages-CmDiPH1A.js → pages-o_YaLL0c.js} +340 -332
- phoenix/version.py +1 -1
- {arize_phoenix-8.4.0.dist-info → arize_phoenix-8.4.1.dist-info}/WHEEL +0 -0
- {arize_phoenix-8.4.0.dist-info → arize_phoenix-8.4.1.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-8.4.0.dist-info → arize_phoenix-8.4.1.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-8.4.0.dist-info → arize_phoenix-8.4.1.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=kpW1WL0kiB8XJsO6XycvZVJ-lBkNoenhQ7atCvBoSe8,5365
|
|
8
8
|
phoenix/settings.py,sha256=ht-0oN-sMV6SPXrk7Tu1EZlngpAYkGNLYPhO8DyrdQI,661
|
|
9
|
-
phoenix/version.py,sha256=
|
|
9
|
+
phoenix/version.py,sha256=6yCd3vhnQem22chqsom8x3AUg4DeTLyaMeAcm2HpMtk,22
|
|
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
|
|
@@ -21,7 +21,7 @@ phoenix/db/enums.py,sha256=tt7iovXLhVTLZ3_LbHNGgcI44SnNjXfkKtLAZG57T54,428
|
|
|
21
21
|
phoenix/db/facilitator.py,sha256=sAYqzBXYSVBKPTQVYrd7ZmtqMAr1zP9dVJwjfNGW7hc,4207
|
|
22
22
|
phoenix/db/helpers.py,sha256=daKbpY2QhTPo9a_T1xNHKI4WzWHkMmmrGIws7Hw-RZ4,4884
|
|
23
23
|
phoenix/db/migrate.py,sha256=oUrXH8yEbcpL4eh09aSCuUiSrhFli0eT5D_j4ZmYChY,2797
|
|
24
|
-
phoenix/db/models.py,sha256=
|
|
24
|
+
phoenix/db/models.py,sha256=wOqbY-pVKa8dw_TKZ23NZuFQHscv4LSKsel_JlBeU2U,45499
|
|
25
25
|
phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
26
|
phoenix/db/insertion/constants.py,sha256=8wifm7X-1XvroZ__R2Gc96NsgLhTDn0zXl4lehlXtcA,70
|
|
27
27
|
phoenix/db/insertion/dataset.py,sha256=I9OC1ouVx7m6BH_c8hvcxW1dWGRAtpvXee29yBTuFkg,7136
|
|
@@ -130,7 +130,7 @@ phoenix/server/api/dataloaders/session_trace_latency_ms_quantile.py,sha256=s_Ce_
|
|
|
130
130
|
phoenix/server/api/dataloaders/span_annotations.py,sha256=y5TvxnljS2P3hm_NiQd24qy313AG76lyjcZFNWGls1A,1028
|
|
131
131
|
phoenix/server/api/dataloaders/span_by_id.py,sha256=gaqsMqMjJfzgsAuC--lZoRvgHk_1o78_0HnpXejg9Bc,1001
|
|
132
132
|
phoenix/server/api/dataloaders/span_dataset_examples.py,sha256=rpBStVP7ZMIH11Cpq4-zCJ4amNC5ZzX72NYv4vAQTdc,1255
|
|
133
|
-
phoenix/server/api/dataloaders/span_descendants.py,sha256=
|
|
133
|
+
phoenix/server/api/dataloaders/span_descendants.py,sha256=xrAJ_pVMQ3G7o4WNn3HxGTpNLCBXJH3xPb1RKnMEd1k,3933
|
|
134
134
|
phoenix/server/api/dataloaders/span_projects.py,sha256=JTfuKn2BBn72QdAP53ZGP2OUCgZJ7AzlzQAx8WivBog,1234
|
|
135
135
|
phoenix/server/api/dataloaders/table_fields.py,sha256=C3ywv87XphMEvqsQGl33H4iOiXbvqWqvaM4Snps4Sv0,3068
|
|
136
136
|
phoenix/server/api/dataloaders/token_counts.py,sha256=Sr_sBfLgsKYCIjgzTFV-fuat7s7DATM2u6ZftLaOnoQ,4629
|
|
@@ -182,7 +182,7 @@ phoenix/server/api/input_types/ProjectSessionSort.py,sha256=qFgLmKYeyFpx7An9ZNdD
|
|
|
182
182
|
phoenix/server/api/input_types/PromptTemplateOptions.py,sha256=8ZJdH1F9fExcdH9dF8SJ29WycCvtEpK-Z6dZwFO7KgQ,232
|
|
183
183
|
phoenix/server/api/input_types/PromptVersionInput.py,sha256=n6zBeSkK8ZFRHTjtVx4BK--azZIxXeYETa6Cufcet2I,3743
|
|
184
184
|
phoenix/server/api/input_types/SpanAnnotationSort.py,sha256=T5pAGzmh4MiJp9JMAzNDByFVTczfw02FH4WFWwFezyI,361
|
|
185
|
-
phoenix/server/api/input_types/SpanSort.py,sha256=
|
|
185
|
+
phoenix/server/api/input_types/SpanSort.py,sha256=oqvcWHYgp_nXvXYNi5l8Bhe7PHT3LbAhUn6ZXDSzdXo,5959
|
|
186
186
|
phoenix/server/api/input_types/TimeRange.py,sha256=pwhC2jx6dFIgT0qFfnO68qiJp9-m7Je5QkNscNsuVxA,700
|
|
187
187
|
phoenix/server/api/input_types/TraceAnnotationSort.py,sha256=BzwiUnMh2VsgQYnhDlbJ6ljHugqIS4YDUlYzvq_tl3o,365
|
|
188
188
|
phoenix/server/api/input_types/UserRoleInput.py,sha256=xxhFe0ITZOgRVEJbVem_W6F1Ip_H6xDENdQqMMx-kKE,129
|
|
@@ -278,7 +278,7 @@ phoenix/server/api/types/Retrieval.py,sha256=OhMK2ncjoyp5h1yjKhjlKpoTbQrMHuxmgSF
|
|
|
278
278
|
phoenix/server/api/types/ScalarDriftMetricEnum.py,sha256=IUAcRPpgL41WdoIgK6cNk2Te38SspXGyEs-S1fY23_A,232
|
|
279
279
|
phoenix/server/api/types/Segments.py,sha256=vT2v0efoa5cuBKxLtxTnsUP5YJJCZfTloM71Spu0tMI,2915
|
|
280
280
|
phoenix/server/api/types/SortDir.py,sha256=OUpXhlCzCxPoXSDkJJygEs9Rw9pMymfaZUG5zPTrw4Y,152
|
|
281
|
-
phoenix/server/api/types/Span.py,sha256=
|
|
281
|
+
phoenix/server/api/types/Span.py,sha256=OJBVbOltdhqbSOepge0qPYS9PBGs2BrA9RyktQ9_otE,25371
|
|
282
282
|
phoenix/server/api/types/SpanAnnotation.py,sha256=6b5G-b_OoRvDL2ayWk7MkbqarLK-F-pQMx21CpUuNGY,1168
|
|
283
283
|
phoenix/server/api/types/SpanIOValue.py,sha256=c5TWdZZN3v0gHI5xWeY7gjD-sE9ugWlGGAio-gDS-Uo,1653
|
|
284
284
|
phoenix/server/api/types/SystemApiKey.py,sha256=2ym8EgsTBIvxx1l9xZ-2YMovz58ZwYb_MaHBTJ9NH2E,166
|
|
@@ -312,10 +312,10 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
312
312
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
313
313
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
314
314
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
315
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
316
|
-
phoenix/server/static/assets/components-
|
|
317
|
-
phoenix/server/static/assets/index-
|
|
318
|
-
phoenix/server/static/assets/pages-
|
|
315
|
+
phoenix/server/static/.vite/manifest.json,sha256=sQ_lHc6TkDsvc2g9rCZb9s_G0YvJMBpzB4MslJGv7Qo,2165
|
|
316
|
+
phoenix/server/static/assets/components-CRlSj2mp.js,sha256=ZN4Xq4Fbtdwg81XezQGRogB0upxqx9MZA4uvPsIo8wc,420595
|
|
317
|
+
phoenix/server/static/assets/index-YUNmSSFA.js,sha256=QQKgYv2KwukZh449x-BfcWEd1DDydJRIZt1bqIhWhNw,59131
|
|
318
|
+
phoenix/server/static/assets/pages-o_YaLL0c.js,sha256=7GvBpyRWdkzw31J2Rx29pz3gGFE9Fha45R---hF2GyM,829587
|
|
319
319
|
phoenix/server/static/assets/vendor-CRRq3WgM.js,sha256=J5mIL57AMCQb5lg2CVj-4e5dGb4NOhDeZNBN61fIROM,2235517
|
|
320
320
|
phoenix/server/static/assets/vendor-Cg6lcjUC.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
|
|
321
321
|
phoenix/server/static/assets/vendor-arizeai-Dq64X_0o.js,sha256=jAFsbq-7Q6v08obSM4NW5oMHsouV6Nd9DDV5A9YqsRE,202331
|
|
@@ -362,9 +362,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
|
|
|
362
362
|
phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
|
|
363
363
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
364
364
|
phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
|
|
365
|
-
arize_phoenix-8.4.
|
|
366
|
-
arize_phoenix-8.4.
|
|
367
|
-
arize_phoenix-8.4.
|
|
368
|
-
arize_phoenix-8.4.
|
|
369
|
-
arize_phoenix-8.4.
|
|
370
|
-
arize_phoenix-8.4.
|
|
365
|
+
arize_phoenix-8.4.1.dist-info/METADATA,sha256=XLNuzNF17bXHp3CKKOqfoAG5DwB_-pP6fRj_AicKVbs,23646
|
|
366
|
+
arize_phoenix-8.4.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
367
|
+
arize_phoenix-8.4.1.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
|
|
368
|
+
arize_phoenix-8.4.1.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
369
|
+
arize_phoenix-8.4.1.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
370
|
+
arize_phoenix-8.4.1.dist-info/RECORD,,
|
phoenix/db/models.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from datetime import datetime, timezone
|
|
2
2
|
from enum import Enum
|
|
3
|
-
from typing import Any, Optional, Sequence, TypedDict
|
|
3
|
+
from typing import Any, Iterable, Optional, Sequence, TypedDict, cast
|
|
4
4
|
|
|
5
5
|
import sqlalchemy.sql as sql
|
|
6
6
|
from openinference.semconv.trace import RerankerAttributes, SpanAttributes
|
|
@@ -39,7 +39,7 @@ from sqlalchemy.orm import (
|
|
|
39
39
|
mapped_column,
|
|
40
40
|
relationship,
|
|
41
41
|
)
|
|
42
|
-
from sqlalchemy.sql import expression
|
|
42
|
+
from sqlalchemy.sql import Values, column, compiler, expression, literal, roles, union_all
|
|
43
43
|
from sqlalchemy.sql.compiler import SQLCompiler
|
|
44
44
|
from sqlalchemy.sql.functions import coalesce
|
|
45
45
|
|
|
@@ -74,6 +74,72 @@ RERANKER_OUTPUT_DOCUMENTS = RerankerAttributes.RERANKER_OUTPUT_DOCUMENTS.split("
|
|
|
74
74
|
RETRIEVAL_DOCUMENTS = SpanAttributes.RETRIEVAL_DOCUMENTS.split(".")
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
class SubValues(Values, roles.CompoundElementRole):
|
|
78
|
+
"""
|
|
79
|
+
Adapted from the following recipe:
|
|
80
|
+
https://github.com/sqlalchemy/sqlalchemy/issues/7228#issuecomment-1746837960
|
|
81
|
+
|
|
82
|
+
This is part of a workaround to make it more convenient to construct the VALUES clause in
|
|
83
|
+
SQLite. The VALUES clause is useful for creating a temporary table in the database with a set
|
|
84
|
+
of user inputs in the form of multi-value tuples, which can then be joined with other tables.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
inherit_cache = True
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def _all_selected_columns(self) -> Iterable[ColumnElement[Any]]:
|
|
91
|
+
return self.columns
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@compiles(SubValues, "sqlite")
|
|
95
|
+
def render_subvalues_w_union(elem: SubValues, compiler: compiler.SQLCompiler, **kw: Any) -> str:
|
|
96
|
+
"""
|
|
97
|
+
Adapted from the following recipe:
|
|
98
|
+
https://github.com/sqlalchemy/sqlalchemy/issues/7228#issuecomment-1746837960
|
|
99
|
+
|
|
100
|
+
This is part of a workaround to make it more convenient to construct the VALUES clause in
|
|
101
|
+
SQLite. The VALUES clause is useful for creating a temporary table in the database with a set
|
|
102
|
+
of user inputs in the form of multi-value tuples, which can then be joined with other tables.
|
|
103
|
+
"""
|
|
104
|
+
# omit rendering parenthesis, columns, "AS name", etc.
|
|
105
|
+
kw.pop("asfrom", None)
|
|
106
|
+
return cast(str, compiler.visit_values(elem, **kw)) # type: ignore[no-untyped-call]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@compiles(Values, "sqlite")
|
|
110
|
+
def render_values_w_union(
|
|
111
|
+
elem: Values,
|
|
112
|
+
compiler: compiler.SQLCompiler,
|
|
113
|
+
from_linter: Optional[compiler.FromLinter] = None,
|
|
114
|
+
**kw: Any,
|
|
115
|
+
) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Adapted from the following recipe:
|
|
118
|
+
https://github.com/sqlalchemy/sqlalchemy/issues/7228#issuecomment-1746837960
|
|
119
|
+
|
|
120
|
+
This is part of a workaround to make it more convenient to construct the VALUES clause in
|
|
121
|
+
SQLite. The VALUES clause is useful for creating a temporary table in the database with a set
|
|
122
|
+
of user inputs in the form of multi-value tuples, which can then be joined with other tables.
|
|
123
|
+
"""
|
|
124
|
+
first: tuple[Any, ...]
|
|
125
|
+
rest: list[tuple[Any, ...]]
|
|
126
|
+
first, *rest = [e for chunk in elem._data for e in chunk]
|
|
127
|
+
stmt = select(*(literal(val).label(col.key) for col, val in zip(elem.columns, first)))
|
|
128
|
+
if rest:
|
|
129
|
+
cols = [column(c.key, c.type) for c in elem.columns]
|
|
130
|
+
stmt = union_all(stmt, SubValues(*cols).data(rest)) # type: ignore[assignment]
|
|
131
|
+
subquery = stmt.subquery(elem.name)
|
|
132
|
+
if from_linter:
|
|
133
|
+
# replace all occurrences of elem with subquery so the from linter
|
|
134
|
+
# can eliminate the values object from its cartesian product check.
|
|
135
|
+
edges = set(from_linter.edges)
|
|
136
|
+
from_linter.edges.clear()
|
|
137
|
+
from_linter.edges.update(
|
|
138
|
+
tuple(subquery if node == elem else node for node in edge) for edge in edges
|
|
139
|
+
)
|
|
140
|
+
return compiler.process(subquery, from_linter=from_linter, **kw)
|
|
141
|
+
|
|
142
|
+
|
|
77
143
|
class AuthMethod(Enum):
|
|
78
144
|
LOCAL = "LOCAL"
|
|
79
145
|
OAUTH2 = "OAUTH2"
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
from
|
|
2
|
-
from typing import Iterable
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from typing import Iterable, Optional
|
|
3
3
|
|
|
4
|
+
import sqlalchemy as sa
|
|
4
5
|
from aioitertools.itertools import groupby
|
|
5
6
|
from sqlalchemy import select
|
|
6
7
|
from strawberry.dataloader import DataLoader
|
|
7
8
|
from typing_extensions import TypeAlias
|
|
8
9
|
|
|
9
|
-
from phoenix.db import
|
|
10
|
+
from phoenix.db.models import Span
|
|
10
11
|
from phoenix.server.types import DbSessionFactory
|
|
11
12
|
|
|
12
13
|
SpanRowId: TypeAlias = int
|
|
14
|
+
MaxDepth: TypeAlias = int
|
|
13
15
|
|
|
14
|
-
Key: TypeAlias = SpanRowId
|
|
16
|
+
Key: TypeAlias = tuple[SpanRowId, Optional[MaxDepth]]
|
|
15
17
|
Result: TypeAlias = list[SpanRowId]
|
|
16
18
|
|
|
17
19
|
|
|
@@ -21,46 +23,81 @@ class SpanDescendantsDataLoader(DataLoader[Key, Result]):
|
|
|
21
23
|
self._db = db
|
|
22
24
|
|
|
23
25
|
async def _load_fn(self, keys: Iterable[Key]) -> list[Result]:
|
|
24
|
-
|
|
26
|
+
# Create a values expression with Span.id and respective max_depth (which can be None).
|
|
27
|
+
values = sa.values(
|
|
28
|
+
sa.Column("root_rowid", sa.Integer),
|
|
29
|
+
sa.Column("max_depth", sa.Integer, nullable=True),
|
|
30
|
+
name="values",
|
|
31
|
+
).data(list(keys))
|
|
32
|
+
|
|
33
|
+
# Get the root spans with their depth limits by joining the values to the Span table.
|
|
34
|
+
roots = (
|
|
25
35
|
select(
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
Span.span_id,
|
|
37
|
+
values.c.root_rowid,
|
|
38
|
+
values.c.max_depth,
|
|
28
39
|
)
|
|
29
|
-
.
|
|
30
|
-
.subquery()
|
|
40
|
+
.join_from(values, Span, Span.id == values.c.root_rowid)
|
|
41
|
+
.subquery("roots")
|
|
31
42
|
)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
|
|
44
|
+
# Initialize the recursive common table expression (CTE) with direct children
|
|
45
|
+
# of root spans, setting depth=1.
|
|
46
|
+
descendants = (
|
|
35
47
|
select(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
Span.id,
|
|
49
|
+
Span.span_id,
|
|
50
|
+
Span.start_time,
|
|
51
|
+
roots.c.root_rowid,
|
|
52
|
+
roots.c.max_depth,
|
|
53
|
+
sa.literal(1).label("depth"), # immediate children are depth=1 from root
|
|
40
54
|
)
|
|
41
|
-
.
|
|
42
|
-
.cte(recursive=True)
|
|
55
|
+
.join_from(roots, Span, Span.parent_id == roots.c.span_id)
|
|
56
|
+
.cte("descendants", recursive=True)
|
|
43
57
|
)
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
|
|
59
|
+
# Build the recursive part of the query to fetch descendants at increasing depths.
|
|
60
|
+
# This recursively finds children of spans in the current depth level.
|
|
61
|
+
parents = descendants.alias("parents")
|
|
62
|
+
descendants = descendants.union_all(
|
|
46
63
|
select(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
Span.id,
|
|
65
|
+
Span.span_id,
|
|
66
|
+
Span.start_time,
|
|
67
|
+
parents.c.root_rowid,
|
|
68
|
+
parents.c.max_depth,
|
|
69
|
+
(parents.c.depth + 1).label("depth"), # Increment depth for each level
|
|
70
|
+
)
|
|
71
|
+
.join_from(parents, Span, Span.parent_id == parents.c.span_id)
|
|
72
|
+
.where(
|
|
73
|
+
sa.or_(
|
|
74
|
+
parents.c.max_depth.is_(None), # No limit if max_depth is NULL
|
|
75
|
+
parents.c.depth + 1 <= parents.c.max_depth, # Stop when max depth is reached
|
|
76
|
+
),
|
|
54
77
|
)
|
|
55
78
|
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
|
|
80
|
+
# Final query to select and order all descendants.
|
|
81
|
+
# Ordering ensures breadth-first traversal and consistent results.
|
|
82
|
+
stmt = select(
|
|
83
|
+
descendants.c.id,
|
|
84
|
+
descendants.c.root_rowid,
|
|
85
|
+
descendants.c.max_depth,
|
|
86
|
+
).order_by(
|
|
87
|
+
descendants.c.root_rowid,
|
|
88
|
+
descendants.c.max_depth,
|
|
89
|
+
descendants.c.depth, # Order by depth for BFS traversal
|
|
90
|
+
descendants.c.start_time,
|
|
91
|
+
descendants.c.id,
|
|
60
92
|
)
|
|
61
|
-
|
|
93
|
+
|
|
94
|
+
results: defaultdict[Key, Result] = defaultdict(list)
|
|
62
95
|
async with self._db() as session:
|
|
63
96
|
data = await session.stream(stmt)
|
|
64
|
-
|
|
65
|
-
|
|
97
|
+
# Group results by root_rowid and max_depth (the Key tuple)
|
|
98
|
+
async for key, group in groupby(data, key=lambda d: tuple(d[1:])):
|
|
99
|
+
# Extract span IDs (the database row IDs) and add them to the result list.
|
|
100
|
+
# The first column (index 0) from our query is Span.id.
|
|
101
|
+
results[key].extend(id_ for id_, *_ in group)
|
|
102
|
+
|
|
66
103
|
return [results[key].copy() for key in keys]
|
phoenix/server/api/types/Span.py
CHANGED
|
@@ -9,7 +9,7 @@ import numpy as np
|
|
|
9
9
|
import strawberry
|
|
10
10
|
from openinference.semconv.trace import SpanAttributes
|
|
11
11
|
from strawberry import ID, UNSET
|
|
12
|
-
from strawberry.relay import Node, NodeID
|
|
12
|
+
from strawberry.relay import Connection, Node, NodeID
|
|
13
13
|
from strawberry.types import Info
|
|
14
14
|
from typing_extensions import Annotated, TypeAlias
|
|
15
15
|
|
|
@@ -30,6 +30,7 @@ from phoenix.server.api.types.Evaluation import DocumentEvaluation
|
|
|
30
30
|
from phoenix.server.api.types.ExampleRevisionInterface import ExampleRevision
|
|
31
31
|
from phoenix.server.api.types.GenerativeProvider import GenerativeProvider
|
|
32
32
|
from phoenix.server.api.types.MimeType import MimeType
|
|
33
|
+
from phoenix.server.api.types.pagination import ConnectionArgs, CursorString, connection_from_list
|
|
33
34
|
from phoenix.server.api.types.SortDir import SortDir
|
|
34
35
|
from phoenix.server.api.types.SpanAnnotation import SpanAnnotation, to_gql_span_annotation
|
|
35
36
|
from phoenix.server.api.types.SpanIOValue import SpanIOValue, truncate_value
|
|
@@ -547,9 +548,31 @@ class Span(Node):
|
|
|
547
548
|
async def descendants(
|
|
548
549
|
self,
|
|
549
550
|
info: Info[Context, None],
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
551
|
+
max_depth: Annotated[
|
|
552
|
+
Optional[int],
|
|
553
|
+
strawberry.argument(
|
|
554
|
+
description="Maximum depth of breadth first search. For example, "
|
|
555
|
+
"maxDepth=1 searches for only the immediate child spans (if any); "
|
|
556
|
+
"maxDepth=2 searches for the immediate child spans plus their children. "
|
|
557
|
+
"maxDepth=0 (or None) means no limit."
|
|
558
|
+
),
|
|
559
|
+
] = 3,
|
|
560
|
+
first: Optional[int] = 50,
|
|
561
|
+
last: Optional[int] = UNSET,
|
|
562
|
+
after: Optional[CursorString] = UNSET,
|
|
563
|
+
before: Optional[CursorString] = UNSET,
|
|
564
|
+
) -> Connection["Span"]:
|
|
565
|
+
args = ConnectionArgs(
|
|
566
|
+
first=first,
|
|
567
|
+
after=after if isinstance(after, CursorString) else None,
|
|
568
|
+
last=last,
|
|
569
|
+
before=before if isinstance(before, CursorString) else None,
|
|
570
|
+
)
|
|
571
|
+
span_rowids: Iterable[int] = await info.context.data_loaders.span_descendants.load(
|
|
572
|
+
(self.span_rowid, max_depth or None),
|
|
573
|
+
)
|
|
574
|
+
data = [Span(span_rowid=span_rowid) for span_rowid in span_rowids]
|
|
575
|
+
return connection_from_list(data=data, args=args)
|
|
553
576
|
|
|
554
577
|
@strawberry.field(
|
|
555
578
|
description="The span's attributes translated into an example revision for a dataset",
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_components-
|
|
3
|
-
"file": "assets/components-
|
|
2
|
+
"_components-CRlSj2mp.js": {
|
|
3
|
+
"file": "assets/components-CRlSj2mp.js",
|
|
4
4
|
"name": "components",
|
|
5
5
|
"imports": [
|
|
6
6
|
"_vendor-CRRq3WgM.js",
|
|
7
|
-
"_pages-
|
|
7
|
+
"_pages-o_YaLL0c.js",
|
|
8
8
|
"_vendor-arizeai-Dq64X_0o.js",
|
|
9
9
|
"_vendor-codemirror-C1oevlym.js",
|
|
10
10
|
"_vendor-three-C-AGeJYv.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
|
-
"_pages-
|
|
14
|
-
"file": "assets/pages-
|
|
13
|
+
"_pages-o_YaLL0c.js": {
|
|
14
|
+
"file": "assets/pages-o_YaLL0c.js",
|
|
15
15
|
"name": "pages",
|
|
16
16
|
"imports": [
|
|
17
17
|
"_vendor-CRRq3WgM.js",
|
|
18
18
|
"_vendor-arizeai-Dq64X_0o.js",
|
|
19
|
-
"_components-
|
|
19
|
+
"_components-CRlSj2mp.js",
|
|
20
20
|
"_vendor-codemirror-C1oevlym.js",
|
|
21
21
|
"_vendor-recharts-CPj01S89.js"
|
|
22
22
|
]
|
|
@@ -69,15 +69,15 @@
|
|
|
69
69
|
"name": "vendor-three"
|
|
70
70
|
},
|
|
71
71
|
"index.tsx": {
|
|
72
|
-
"file": "assets/index-
|
|
72
|
+
"file": "assets/index-YUNmSSFA.js",
|
|
73
73
|
"name": "index",
|
|
74
74
|
"src": "index.tsx",
|
|
75
75
|
"isEntry": true,
|
|
76
76
|
"imports": [
|
|
77
77
|
"_vendor-CRRq3WgM.js",
|
|
78
78
|
"_vendor-arizeai-Dq64X_0o.js",
|
|
79
|
-
"_pages-
|
|
80
|
-
"_components-
|
|
79
|
+
"_pages-o_YaLL0c.js",
|
|
80
|
+
"_components-CRlSj2mp.js",
|
|
81
81
|
"_vendor-three-C-AGeJYv.js",
|
|
82
82
|
"_vendor-codemirror-C1oevlym.js",
|
|
83
83
|
"_vendor-shiki-aY7rz1pm.js",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as g,R as j,j as e,u as ba,a as Me,e as a1,s as V1,b as D1,c as $e,d as Q1,f as gi,g as fe,h as hi,i as fi,k as q1,l,m as Ci,n as Te,C as o1,o as We,p as Qe,q as bi,t as vi,v as R,w as ln,L as va,x as ya,y as La,z as ce,A as v,B as g1,D as sn,E as p,F as wa,$ as yi,G as xa,H as ka,I as xe,J as Li,K as cn,M as wi,N as xi,O as q,P as X1,Q as O,S as K,T as N,U as Sa,V as Ma,W as ki,X as h1,Y as Ta,Z as Si,_ as Mi,a0 as Ti,a1 as Ii,a2 as Ai,a3 as zi,a4 as Ei,a5 as Vi,a6 as f1,a7 as Di,a8 as Pi,a9 as Oi,aa as _i,ab as ke,ac as Y1,ad as J1,ae as en,af as F,ag as Oe,ah as _n,ai as Fi,aj as Ri,ak as Ni,al as Ia,am as Hi,an as _,ao as Aa,ap as Ki,aq as ze,ar as dn,as as $i,at as un,au as Bi,av as Zi,aw as Gi,ax as ji,ay as Ui,az as Wi,aA as Fn,aB as Qi,aC as qi,aD as Xi,aE as Rn,aF as Yi,aG as Ji,aH as er,aI as P1,aJ as nr,aK as ar,aL as tr,aM as ir,aN as rr,aO as or,aP as lr,aQ as sr,aR as cr,aS as dr}from"./vendor-CRRq3WgM.js";import{a as Nn,R as ur,b as mr,c as pr,m as gr,T as hr,u as fr}from"./pages-
|
|
1
|
+
import{r as g,R as j,j as e,u as ba,a as Me,e as a1,s as V1,b as D1,c as $e,d as Q1,f as gi,g as fe,h as hi,i as fi,k as q1,l,m as Ci,n as Te,C as o1,o as We,p as Qe,q as bi,t as vi,v as R,w as ln,L as va,x as ya,y as La,z as ce,A as v,B as g1,D as sn,E as p,F as wa,$ as yi,G as xa,H as ka,I as xe,J as Li,K as cn,M as wi,N as xi,O as q,P as X1,Q as O,S as K,T as N,U as Sa,V as Ma,W as ki,X as h1,Y as Ta,Z as Si,_ as Mi,a0 as Ti,a1 as Ii,a2 as Ai,a3 as zi,a4 as Ei,a5 as Vi,a6 as f1,a7 as Di,a8 as Pi,a9 as Oi,aa as _i,ab as ke,ac as Y1,ad as J1,ae as en,af as F,ag as Oe,ah as _n,ai as Fi,aj as Ri,ak as Ni,al as Ia,am as Hi,an as _,ao as Aa,ap as Ki,aq as ze,ar as dn,as as $i,at as un,au as Bi,av as Zi,aw as Gi,ax as ji,ay as Ui,az as Wi,aA as Fn,aB as Qi,aC as qi,aD as Xi,aE as Rn,aF as Yi,aG as Ji,aH as er,aI as P1,aJ as nr,aK as ar,aL as tr,aM as ir,aN as rr,aO as or,aP as lr,aQ as sr,aR as cr,aS as dr}from"./vendor-CRRq3WgM.js";import{a as Nn,R as ur,b as mr,c as pr,m as gr,T as hr,u as fr}from"./pages-o_YaLL0c.js";import{u as Cr,_ as za,a as re,T as X,E as Ea,b as br,c as vr,d as Se,D as C1,e as ye,f as yr,g as _e,A as qe,C as b1,P as mn,F as Lr,L as ve,h as Va,i as l1,j as v1,I as pn,k as gn,l as Da,m as wr,n as xr,o as Pa,p as kr,q as Sr,r as Mr,s as Oa,t as _a,v as Tr,w as Ir,x as Hn,y as Ar}from"./vendor-arizeai-Dq64X_0o.js";import{L as Fa,a as Ra,j as Na,E as hn,k as Ha,d as Ka,l as nn,b as $a,h as zr,c as Er,e as Vr,f as Dr,g as Pr,i as Or,s as _r,m as Ba,n as Xe,R as Ye,p as Fr,o as Rr}from"./vendor-codemirror-C1oevlym.js";import{V as Nr}from"./vendor-three-C-AGeJYv.js";const Za=function(){var n={defaultValue:null,kind:"LocalArgument",name:"clusters"},a={defaultValue:null,kind:"LocalArgument",name:"dataQualityMetricColumnName"},t={defaultValue:null,kind:"LocalArgument",name:"fetchDataQualityMetric"},i={defaultValue:null,kind:"LocalArgument",name:"fetchPerformanceMetric"},r={defaultValue:null,kind:"LocalArgument",name:"performanceMetric"},o=[{alias:null,args:null,kind:"ScalarField",name:"primaryValue",storageKey:null},{alias:null,args:null,kind:"ScalarField",name:"referenceValue",storageKey:null}],s=[{alias:null,args:[{kind:"Variable",name:"clusters",variableName:"clusters"}],concreteType:"Cluster",kind:"LinkedField",name:"clusters",plural:!0,selections:[{alias:null,args:null,kind:"ScalarField",name:"id",storageKey:null},{alias:null,args:null,kind:"ScalarField",name:"eventIds",storageKey:null},{alias:null,args:null,kind:"ScalarField",name:"driftRatio",storageKey:null},{alias:null,args:null,kind:"ScalarField",name:"primaryToCorpusRatio",storageKey:null},{condition:"fetchDataQualityMetric",kind:"Condition",passingValue:!0,selections:[{alias:null,args:[{fields:[{kind:"Variable",name:"columnName",variableName:"dataQualityMetricColumnName"},{kind:"Literal",name:"metric",value:"mean"}],kind:"ObjectValue",name:"metric"}],concreteType:"DatasetValues",kind:"LinkedField",name:"dataQualityMetric",plural:!1,selections:o,storageKey:null}]},{condition:"fetchPerformanceMetric",kind:"Condition",passingValue:!0,selections:[{alias:null,args:[{fields:[{kind:"Variable",name:"metric",variableName:"performanceMetric"}],kind:"ObjectValue",name:"metric"}],concreteType:"DatasetValues",kind:"LinkedField",name:"performanceMetric",plural:!1,selections:o,storageKey:null}]}],storageKey:null}];return{fragment:{argumentDefinitions:[n,a,t,i,r],kind:"Fragment",metadata:null,name:"pointCloudStore_clusterMetricsQuery",selections:s,type:"Query",abstractKey:null},kind:"Request",operation:{argumentDefinitions:[n,t,a,i,r],kind:"Operation",name:"pointCloudStore_clusterMetricsQuery",selections:s},params:{cacheID:"86666967012812887ac0a0149d2d2535",id:null,metadata:{},name:"pointCloudStore_clusterMetricsQuery",operationKind:"query",text:`query pointCloudStore_clusterMetricsQuery(
|
|
2
2
|
$clusters: [ClusterInput!]!
|
|
3
3
|
$fetchDataQualityMetric: Boolean!
|
|
4
4
|
$dataQualityMetricColumnName: String
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as t,j as o,ba as z,l as c,O as w,R as P,E as b,cm as k,e1 as S,e2 as F,e3 as L,e4 as l,v as C,e5 as E}from"./vendor-CRRq3WgM.js";import{d as R,J as I,D as T,V as j,W as _}from"./vendor-arizeai-Dq64X_0o.js";import{L as A,r as D,d as O,e as G,F as N,f as V,P as M,h as W,M as m,g as U,D as q,i as B,E as J,j as K,k as $,p as H,l as Y,n as p,o as Q,q as X,s as Z,S as oo,t as lo,v as ao,w as ro,x as co,y as u,z as f,A as y,B as go,C as eo,G as bo,H as no,I as io,J as so,K as to,N as mo,O as po,Q as uo,U as fo,V as yo,W as ho,X as vo,Y as xo,Z as zo,_ as wo,$ as Po,a0 as ko,a1 as So,a2 as Fo,a3 as Lo,a4 as Co,a5 as Eo,a6 as Ro,a7 as Io,a8 as To,a9 as jo,aa as _o,ab as Ao,ac as Do}from"./pages-
|
|
1
|
+
import{r as t,j as o,ba as z,l as c,O as w,R as P,E as b,cm as k,e1 as S,e2 as F,e3 as L,e4 as l,v as C,e5 as E}from"./vendor-CRRq3WgM.js";import{d as R,J as I,D as T,V as j,W as _}from"./vendor-arizeai-Dq64X_0o.js";import{L as A,r as D,d as O,e as G,F as N,f as V,P as M,h as W,M as m,g as U,D as q,i as B,E as J,j as K,k as $,p as H,l as Y,n as p,o as Q,q as X,s as Z,S as oo,t as lo,v as ao,w as ro,x as co,y as u,z as f,A as y,B as go,C as eo,G as bo,H as no,I as io,J as so,K as to,N as mo,O as po,Q as uo,U as fo,V as yo,W as ho,X as vo,Y as xo,Z as zo,_ as wo,$ as Po,a0 as ko,a1 as So,a2 as Fo,a3 as Lo,a4 as Co,a5 as Eo,a6 as Ro,a7 as Io,a8 as To,a9 as jo,aa as _o,ab as Ao,ac as Do}from"./pages-o_YaLL0c.js";import{W as Oo,dB as Go,b9 as No,U as Vo,dC as Mo,dD as Wo}from"./components-CRlSj2mp.js";import"./vendor-three-C-AGeJYv.js";import"./vendor-codemirror-C1oevlym.js";import"./vendor-shiki-aY7rz1pm.js";import"./vendor-recharts-CPj01S89.js";(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const g of r)if(g.type==="childList")for(const n of g.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&s(n)}).observe(document,{childList:!0,subtree:!0});function i(r){const g={};return r.integrity&&(g.integrity=r.integrity),r.referrerPolicy&&(g.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?g.credentials="include":r.crossOrigin==="anonymous"?g.credentials="omit":g.credentials="same-origin",g}function s(r){if(r.ep)return;r.ep=!0;const g=i(r);fetch(r.href,g)}})();const h="arize-phoenix-feature-flags",d={__RESET__:!1};function Uo(){const a=localStorage.getItem(h);if(!a)return d;try{const e=JSON.parse(a);return Object.assign({},d,e)}catch{return d}}const v=t.createContext(null);function qo(){const a=P.useContext(v);if(a===null)throw new Error("useFeatureFlags must be used within a FeatureFlagsProvider");return a}function Bo(a){const[e,i]=t.useState(Uo()),s=r=>{localStorage.setItem(h,JSON.stringify(r)),i(r)};return o(v.Provider,{value:{featureFlags:e,setFeatureFlags:s},children:o(Jo,{children:a.children})})}function Jo(a){const{children:e}=a,{featureFlags:i,setFeatureFlags:s}=qo(),[r,g]=t.useState(!1);return z("ctrl+shift+f",()=>g(!0)),c(w,{children:[e,o(T,{type:"modal",isDismissable:!0,onDismiss:()=>g(!1),children:r&&o(R,{title:"Feature Flags",children:o(Oo,{height:"size-1000",padding:"size-100",children:Object.keys(i).map(n=>o(I,{isSelected:i[n],onChange:x=>s({...i,[n]:x}),children:n},n))})})})]})}const Ko=b`
|
|
2
2
|
:root {
|
|
3
3
|
--ac-global-dimension-scale-factor: 1;
|
|
4
4
|
--ac-global-dimension-size-0: 0px;
|