arize-phoenix 3.14.2__py3-none-any.whl → 3.15.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-3.14.2.dist-info → arize_phoenix-3.15.1.dist-info}/METADATA +1 -1
- {arize_phoenix-3.14.2.dist-info → arize_phoenix-3.15.1.dist-info}/RECORD +26 -25
- phoenix/config.py +30 -1
- phoenix/core/project.py +8 -0
- phoenix/core/traces.py +20 -4
- phoenix/server/api/routers/evaluation_handler.py +3 -2
- phoenix/server/api/routers/span_handler.py +1 -1
- phoenix/server/api/routers/trace_handler.py +1 -1
- phoenix/server/api/schema.py +27 -5
- phoenix/server/api/types/Span.py +16 -6
- phoenix/server/app.py +1 -1
- phoenix/server/main.py +4 -22
- phoenix/server/static/index.js +452 -432
- phoenix/session/client.py +52 -11
- phoenix/session/session.py +9 -0
- phoenix/storage/span_store/__init__.py +23 -0
- phoenix/trace/__init__.py +8 -1
- phoenix/trace/dsl/helpers.py +10 -4
- phoenix/trace/projects.py +13 -3
- phoenix/utilities/project.py +1 -1
- phoenix/utilities/span_store.py +23 -0
- phoenix/version.py +1 -1
- phoenix/storage/spanstore/__init__.py +0 -9
- {arize_phoenix-3.14.2.dist-info → arize_phoenix-3.15.1.dist-info}/WHEEL +0 -0
- {arize_phoenix-3.14.2.dist-info → arize_phoenix-3.15.1.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-3.14.2.dist-info → arize_phoenix-3.15.1.dist-info}/licenses/LICENSE +0 -0
- /phoenix/storage/{spanstore → span_store}/text_file.py +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
phoenix/__init__.py,sha256=mrgR7rvpc7LnBeyLzCX9wmRP4kJSJdfKDbj2zDiDjG8,2311
|
|
2
|
-
phoenix/config.py,sha256=
|
|
2
|
+
phoenix/config.py,sha256=iGZeRwpvQG-JOzlfv642f98rCAHQ1SpGiEvgJsxg-1g,4682
|
|
3
3
|
phoenix/datetime_utils.py,sha256=D955QLrkgrrSdUM6NyqbCeAu2SMsjhR5rHVQEsVUdng,2773
|
|
4
4
|
phoenix/exceptions.py,sha256=X5k9ipUDfwSCwZB-H5zFJLas86Gf9tAx0W4l5TZxp5k,108
|
|
5
5
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
6
6
|
phoenix/services.py,sha256=f6AeyKTuOpy9RCcTCjVH3gx5nYZhbTMFOuv1WSUOB5o,4992
|
|
7
|
-
phoenix/version.py,sha256=
|
|
7
|
+
phoenix/version.py,sha256=ZkLw4mpKHbvgufoRYVg6ykxZYyu0FTe3IZCKsCUV2x4,23
|
|
8
8
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
10
10
|
phoenix/core/model.py,sha256=C-kDATyJEgP-oqYVKOiQM76Ljs66F6VZdT93_b8kTGk,4725
|
|
11
11
|
phoenix/core/model_schema.py,sha256=lQaTvKS34yurHOJ53YD020uURLfgG3dqKC1NLQftOjA,50222
|
|
12
12
|
phoenix/core/model_schema_adapter.py,sha256=3GkyzqUST4fYi-Bgs8qAam5hwMCdQRZTDLjZ9Bnzdm4,8268
|
|
13
|
-
phoenix/core/project.py,sha256=
|
|
14
|
-
phoenix/core/traces.py,sha256=
|
|
13
|
+
phoenix/core/project.py,sha256=KBntQewZ02XkU9GIHFlncTHjPFokTeCTMY5pQpg8HkE,24817
|
|
14
|
+
phoenix/core/traces.py,sha256=54Xsp-rBMMdeT8KDVrK1M7g4QGXHFlKgVfVEs5KnQzg,3549
|
|
15
15
|
phoenix/datasets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
phoenix/datasets/dataset.py,sha256=scKVZ7zc6Dpc_ntt-pWhzY-KWqOJEwKePuyNnKSVTGE,30515
|
|
17
17
|
phoenix/datasets/errors.py,sha256=cGp9vxnw4SewFoWBV3ZGMkhE0Kh73lPIv3Ppz_H_RoA,8261
|
|
@@ -55,14 +55,14 @@ phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYG
|
|
|
55
55
|
phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
|
|
56
56
|
phoenix/pointcloud/umap_parameters.py,sha256=lJsEOrbSuSiqI7g4Yt6xj7kgYxEqoep4ZHWLr6VWBqw,1760
|
|
57
57
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
|
-
phoenix/server/app.py,sha256=
|
|
59
|
-
phoenix/server/main.py,sha256=
|
|
58
|
+
phoenix/server/app.py,sha256=7yGzmItFLoTFa5CBZwz4Qb2VZbVbczh_3qRqTTtkaKw,6888
|
|
59
|
+
phoenix/server/main.py,sha256=wrKegfYm-5APU0CqPqpEE_3MUlSgU2LPfpEkYSd870E,9457
|
|
60
60
|
phoenix/server/thread_server.py,sha256=dP6cm6Cf08jNhDA1TRlVZpziu1YgtPDmaeIJMm725eI,2154
|
|
61
61
|
phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
62
|
phoenix/server/api/context.py,sha256=wjCzq4QlszKG1iN-xgu5rRLYPqdvTFqX02aFYPipNoQ,512
|
|
63
63
|
phoenix/server/api/helpers.py,sha256=_V1eVkchZmTkhOfRC4QqR1sUB2xtIxdsMJkDouZq_IE,251
|
|
64
64
|
phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
|
|
65
|
-
phoenix/server/api/schema.py,sha256=
|
|
65
|
+
phoenix/server/api/schema.py,sha256=UpYm8wFwHeQfSX25WwDkhBPilIjiXQ4PSoQUclv3IHc,8839
|
|
66
66
|
phoenix/server/api/input_types/ClusterInput.py,sha256=EL4ftvZxQ8mVdruUPcdhMhByORmSmM8S-X6RPqU6GX0,179
|
|
67
67
|
phoenix/server/api/input_types/Coordinates.py,sha256=meTwbIjwTfqx5DGD2DBlH9wQzdQVNM5a8x9dp1FfIgA,173
|
|
68
68
|
phoenix/server/api/input_types/DataQualityMetricInput.py,sha256=LazvmQCCM5m9SDZTpyxQXO1rYF4cmsc3lsR2S9S65X4,1292
|
|
@@ -74,9 +74,9 @@ phoenix/server/api/input_types/SpanSort.py,sha256=3ken7KaDUwoZfhaSiP9QRhkNPgGrCY
|
|
|
74
74
|
phoenix/server/api/input_types/TimeRange.py,sha256=yzx-gxj8mDeGLft1FzU_x1MVEgIG5Pt6-f8PUVDgipQ,522
|
|
75
75
|
phoenix/server/api/input_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
76
|
phoenix/server/api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
|
-
phoenix/server/api/routers/evaluation_handler.py,sha256=
|
|
78
|
-
phoenix/server/api/routers/span_handler.py,sha256=
|
|
79
|
-
phoenix/server/api/routers/trace_handler.py,sha256=
|
|
77
|
+
phoenix/server/api/routers/evaluation_handler.py,sha256=IkVKe2CMEaHNb_k_eGq1PWBURfbhcg0KjI7m0Eh-9wc,3949
|
|
78
|
+
phoenix/server/api/routers/span_handler.py,sha256=IM4eiQ7GMU7JVyf0oMbrzEcItVudLy_CeYaWcwHOby4,2387
|
|
79
|
+
phoenix/server/api/routers/trace_handler.py,sha256=0Y9QlePySJZyhKJLWM-m1e837HMZm5QcKR-iXshQdG4,2413
|
|
80
80
|
phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
|
|
81
81
|
phoenix/server/api/types/Cluster.py,sha256=R08ZKrLl1KK8colxHU57N5XIOTMUwg5ZI50ofPoxxSM,5618
|
|
82
82
|
phoenix/server/api/types/DataQualityMetric.py,sha256=zRKsNvHBu-NdcsunuLhqFpZhi6ks-HMqA1PJD27jTak,590
|
|
@@ -109,7 +109,7 @@ phoenix/server/api/types/Retrieval.py,sha256=OhMK2ncjoyp5h1yjKhjlKpoTbQrMHuxmgSF
|
|
|
109
109
|
phoenix/server/api/types/ScalarDriftMetricEnum.py,sha256=IUAcRPpgL41WdoIgK6cNk2Te38SspXGyEs-S1fY23_A,232
|
|
110
110
|
phoenix/server/api/types/Segments.py,sha256=B6UUWjalZONjWjl_l61A6USPSu15ICXRgzZ4m3vA1yw,2921
|
|
111
111
|
phoenix/server/api/types/SortDir.py,sha256=OUpXhlCzCxPoXSDkJJygEs9Rw9pMymfaZUG5zPTrw4Y,152
|
|
112
|
-
phoenix/server/api/types/Span.py,sha256=
|
|
112
|
+
phoenix/server/api/types/Span.py,sha256=qyJgHpj9MkYl_xsLfVm5XvoDCRkFYEt-xVNQJ4MUVow,12678
|
|
113
113
|
phoenix/server/api/types/TimeSeries.py,sha256=QbLfxHnwYsMsirpq4tx9us6ha7YtAVzK4m8mAL3fMt0,5200
|
|
114
114
|
phoenix/server/api/types/UMAPPoints.py,sha256=8l9RJXi308qty4MdHb2pBbiU6ZuLbrRRxXNbPhXoxKI,1639
|
|
115
115
|
phoenix/server/api/types/ValidationResult.py,sha256=pHwdYk4J7SJ5xhlWWHg_6qWkfk4rjOx-bSkGHvkDE3Q,142
|
|
@@ -127,25 +127,25 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
127
127
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
128
128
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
129
129
|
phoenix/server/static/index.css,sha256=KKGpx4iwF91VGRm0YN-4cn8oC-oIqC6HecoPf0x3ZM8,1885
|
|
130
|
-
phoenix/server/static/index.js,sha256
|
|
130
|
+
phoenix/server/static/index.js,sha256=yw3BlmllF9--GmxXZYWUqIkMA-hElFhd9kAVNphSoCE,3176874
|
|
131
131
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
132
132
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
133
133
|
phoenix/server/templates/index.html,sha256=lO2wGA5XsftPg03rw_VcyaYf_4vegtlWbIT5ms4fA_c,1982
|
|
134
134
|
phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
135
|
-
phoenix/session/client.py,sha256=
|
|
135
|
+
phoenix/session/client.py,sha256=EMhzmsqquZbuuH0NX137npYLVJWEKI5OieeCBsVGh3A,7933
|
|
136
136
|
phoenix/session/data_extractor.py,sha256=0Kf-2mKY_YbYoD2fZkAYpKdFgsXrC3OKQ5d2iZsGgAI,1947
|
|
137
137
|
phoenix/session/evaluation.py,sha256=YCv1XkWHi7vM_W5V7rorrrAxadv78wuMPeCVJvf5-oE,5444
|
|
138
|
-
phoenix/session/session.py,sha256=
|
|
138
|
+
phoenix/session/session.py,sha256=9NsZCvrozDfFNc2b4dhadSuYHAO7rJLCvrgA0qangqg,24919
|
|
139
139
|
phoenix/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
140
|
-
phoenix/storage/
|
|
141
|
-
phoenix/storage/
|
|
142
|
-
phoenix/trace/__init__.py,sha256=
|
|
140
|
+
phoenix/storage/span_store/__init__.py,sha256=ib-1BWPX4zMfIxS_qC-intyZciGMBJkAOcpb06d3jgQ,586
|
|
141
|
+
phoenix/storage/span_store/text_file.py,sha256=Fzpl_UDVN6_Qa8kpjhDkjdO7xb_I3g-UuTseenkV42c,2853
|
|
142
|
+
phoenix/trace/__init__.py,sha256=hXo7FzA-utf7CD9PiZQYfQ-0irqHVzfSA4j_RLSmKK4,891
|
|
143
143
|
phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
|
|
144
144
|
phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
|
|
145
145
|
phoenix/trace/exporter.py,sha256=vh2RO1CpP143HxIX94KV0qks8p1x66RE3Tgf8kcBCCg,4519
|
|
146
146
|
phoenix/trace/fixtures.py,sha256=HOjuYOB_xtR7JUeLz7WpEroiGj4E5_SxVLSjBYUy8RQ,7055
|
|
147
147
|
phoenix/trace/otel.py,sha256=mpuj_eOdBUPAcslpxk8XZflb9kkzpMJ8X9acJS8ACPA,15322
|
|
148
|
-
phoenix/trace/projects.py,sha256=
|
|
148
|
+
phoenix/trace/projects.py,sha256=2BwlNjFE-uwpqYtCu5YyBiYZk9wRPpM13vh3-Cv7GkA,2157
|
|
149
149
|
phoenix/trace/schemas.py,sha256=6PVPnQIIDsWijwCwU19TGKG3xhFCYFY9K_5IqR5dWF4,5904
|
|
150
150
|
phoenix/trace/span_evaluations.py,sha256=T67grfU71iANMM0g6dp2OQ_ZjtkON2viZz95_U9FLQA,12954
|
|
151
151
|
phoenix/trace/span_json_decoder.py,sha256=IAFakPRqSMYxTPKYFMiXYxm7U-FipdN8_xbvapDS0Qc,3131
|
|
@@ -154,7 +154,7 @@ phoenix/trace/trace_dataset.py,sha256=RpHIfZLbMmULOIb-fKXJkQLhIdC0sJlAOTjlyJppMY
|
|
|
154
154
|
phoenix/trace/utils.py,sha256=7LurVGXn245cjj4MJsc7v6jq4DSJkpK6YGBfIaSywuw,1307
|
|
155
155
|
phoenix/trace/dsl/__init__.py,sha256=WIQIjJg362XD3s50OsPJJ0xbDsGp41bSv7vDllLrPuA,144
|
|
156
156
|
phoenix/trace/dsl/filter.py,sha256=paLpcSMnHdgCfcvcroaqOoCe2retAZ5ocp_5cNTnv9s,14167
|
|
157
|
-
phoenix/trace/dsl/helpers.py,sha256=
|
|
157
|
+
phoenix/trace/dsl/helpers.py,sha256=TG8EFZAjvRwjXpxitEGAc4QpF3vn4jpqhI_Tcwp5mE4,2134
|
|
158
158
|
phoenix/trace/dsl/missing.py,sha256=BWPOHr2_tBkPDgVeq8GVXXVbNbJiBelu4NtwHBg6mTE,1435
|
|
159
159
|
phoenix/trace/dsl/query.py,sha256=k0guhWBEo6L7ZJH5FJs2-iGSnWXdUUqu09gd-8M4CGg,14783
|
|
160
160
|
phoenix/trace/langchain/__init__.py,sha256=F37GfD1pd5Kuw7R7iRUM1zXXpO8xEcycNZh5dwqBXNk,109
|
|
@@ -169,9 +169,10 @@ phoenix/trace/v1/evaluation_pb2.pyi,sha256=cCbbx06gwQmaH14s3J1X25TtaARh-k1abbxQd
|
|
|
169
169
|
phoenix/utilities/__init__.py,sha256=8w1Ivw0KO9YKWrhcdnO73cSVqP9VHAp0pSfsi_oDiuQ,672
|
|
170
170
|
phoenix/utilities/error_handling.py,sha256=7b5rpGFj9EWZ8yrZK1IHvxB89suWk3lggDayUQcvZds,1946
|
|
171
171
|
phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,222
|
|
172
|
-
phoenix/utilities/project.py,sha256=
|
|
173
|
-
|
|
174
|
-
arize_phoenix-3.
|
|
175
|
-
arize_phoenix-3.
|
|
176
|
-
arize_phoenix-3.
|
|
177
|
-
arize_phoenix-3.
|
|
172
|
+
phoenix/utilities/project.py,sha256=qWsvKnG1oKhOFUowXf9qiOL2ia7jaFe_ijFFHEt8GJo,431
|
|
173
|
+
phoenix/utilities/span_store.py,sha256=13UK0rE4wQd70yl___WsDRnH0ru-xErng9_Ml7zfEwE,978
|
|
174
|
+
arize_phoenix-3.15.1.dist-info/METADATA,sha256=Gz78s9n05nQlE0BgDupaBvSpJs8ldCrwtM_rWV7DnpQ,29204
|
|
175
|
+
arize_phoenix-3.15.1.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
|
|
176
|
+
arize_phoenix-3.15.1.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
177
|
+
arize_phoenix-3.15.1.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
178
|
+
arize_phoenix-3.15.1.dist-info/RECORD,,
|
phoenix/config.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import tempfile
|
|
3
|
+
from enum import Enum
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import List, Optional
|
|
5
6
|
|
|
@@ -21,6 +22,11 @@ ENV_PHOENIX_PROJECT_NAME = "PHOENIX_PROJECT_NAME"
|
|
|
21
22
|
"""
|
|
22
23
|
The project name to use when logging traces and evals. defaults to 'default'.
|
|
23
24
|
"""
|
|
25
|
+
ENV_SPAN_STORAGE_TYPE = "__DANGEROUS__PHOENIX_SPAN_STORAGE_TYPE"
|
|
26
|
+
"""
|
|
27
|
+
**EXPERIMENTAL**
|
|
28
|
+
The type of span storage to use.
|
|
29
|
+
"""
|
|
24
30
|
|
|
25
31
|
|
|
26
32
|
def _get_temp_path() -> Path:
|
|
@@ -127,4 +133,27 @@ def get_env_collector_endpoint() -> Optional[str]:
|
|
|
127
133
|
|
|
128
134
|
|
|
129
135
|
def get_env_project_name() -> str:
|
|
130
|
-
return os.getenv(ENV_PHOENIX_PROJECT_NAME) or
|
|
136
|
+
return os.getenv(ENV_PHOENIX_PROJECT_NAME) or DEFAULT_PROJECT_NAME
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def get_env_span_storage_type() -> Optional["SpanStorageType"]:
|
|
140
|
+
"""
|
|
141
|
+
Get the type of span storage to use.
|
|
142
|
+
"""
|
|
143
|
+
if not (env_type_str := os.getenv(ENV_SPAN_STORAGE_TYPE)):
|
|
144
|
+
return None
|
|
145
|
+
try:
|
|
146
|
+
return SpanStorageType(env_type_str.lower())
|
|
147
|
+
except ValueError:
|
|
148
|
+
raise ValueError(
|
|
149
|
+
f"⚠️ Invalid span storage type value `{env_type_str}` defined by the "
|
|
150
|
+
f"environment variable `{ENV_SPAN_STORAGE_TYPE}`. Valid values are: "
|
|
151
|
+
f"{', '.join(t.value for t in SpanStorageType)}."
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class SpanStorageType(Enum):
|
|
156
|
+
TEXT_FILES = "text-files"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
DEFAULT_PROJECT_NAME = "default"
|
phoenix/core/project.py
CHANGED
|
@@ -91,6 +91,7 @@ class Project:
|
|
|
91
91
|
def __init__(self) -> None:
|
|
92
92
|
self._spans = _Spans()
|
|
93
93
|
self._evals = _Evals()
|
|
94
|
+
self._is_archived = False
|
|
94
95
|
|
|
95
96
|
@property
|
|
96
97
|
def last_updated_at(self) -> Optional[datetime]:
|
|
@@ -192,6 +193,13 @@ class Project:
|
|
|
192
193
|
def export_evaluations(self) -> List[Evaluations]:
|
|
193
194
|
return self._evals.export_evaluations()
|
|
194
195
|
|
|
196
|
+
def archive(self) -> None:
|
|
197
|
+
self._is_archived = True
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def is_archived(self) -> bool:
|
|
201
|
+
return self._is_archived
|
|
202
|
+
|
|
195
203
|
|
|
196
204
|
class _Spans:
|
|
197
205
|
def __init__(self) -> None:
|
phoenix/core/traces.py
CHANGED
|
@@ -8,13 +8,13 @@ from typing import DefaultDict, Iterator, Optional, Tuple, Union
|
|
|
8
8
|
from typing_extensions import assert_never
|
|
9
9
|
|
|
10
10
|
import phoenix.trace.v1 as pb
|
|
11
|
+
from phoenix.config import DEFAULT_PROJECT_NAME
|
|
11
12
|
from phoenix.core.project import (
|
|
12
13
|
END_OF_QUEUE,
|
|
13
14
|
Project,
|
|
14
15
|
_ProjectName,
|
|
15
16
|
)
|
|
16
17
|
from phoenix.trace.schemas import Span
|
|
17
|
-
from phoenix.utilities.project import DEFAULT_PROJECT_NAME
|
|
18
18
|
|
|
19
19
|
_SpanItem = Tuple[Span, _ProjectName]
|
|
20
20
|
_EvalItem = Tuple[pb.Evaluation, _ProjectName]
|
|
@@ -38,10 +38,26 @@ class Traces:
|
|
|
38
38
|
with self._lock:
|
|
39
39
|
return self._projects.get(project_name)
|
|
40
40
|
|
|
41
|
-
def get_projects(self) -> Iterator[Tuple[str, "Project"]]:
|
|
41
|
+
def get_projects(self) -> Iterator[Tuple[int, str, "Project"]]:
|
|
42
42
|
with self._lock:
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
for project_id, (project_name, project) in enumerate(self._projects.items()):
|
|
44
|
+
if project.is_archived:
|
|
45
|
+
continue
|
|
46
|
+
yield project_id, project_name, project
|
|
47
|
+
|
|
48
|
+
def archive_project(self, id: int) -> Optional["Project"]:
|
|
49
|
+
with self._lock:
|
|
50
|
+
active_projects = {
|
|
51
|
+
project_id: project
|
|
52
|
+
for project_id, _, project in self.get_projects()
|
|
53
|
+
if not project.is_archived
|
|
54
|
+
}
|
|
55
|
+
if len(active_projects) <= 1:
|
|
56
|
+
return None
|
|
57
|
+
if project := active_projects.get(id):
|
|
58
|
+
project.archive()
|
|
59
|
+
return project
|
|
60
|
+
return None
|
|
45
61
|
|
|
46
62
|
def put(
|
|
47
63
|
self,
|
|
@@ -15,11 +15,11 @@ from starlette.status import (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
import phoenix.trace.v1 as pb
|
|
18
|
+
from phoenix.config import DEFAULT_PROJECT_NAME
|
|
18
19
|
from phoenix.core.traces import Traces
|
|
19
20
|
from phoenix.server.api.routers.utils import table_to_bytes
|
|
20
21
|
from phoenix.session.evaluation import encode_evaluations
|
|
21
22
|
from phoenix.trace.span_evaluations import Evaluations
|
|
22
|
-
from phoenix.utilities.project import DEFAULT_PROJECT_NAME
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class EvaluationHandler(HTTPEndpoint):
|
|
@@ -27,6 +27,7 @@ class EvaluationHandler(HTTPEndpoint):
|
|
|
27
27
|
|
|
28
28
|
async def post(self, request: Request) -> Response:
|
|
29
29
|
content_type = request.headers.get("content-type")
|
|
30
|
+
project_name = request.headers.get("project-name", DEFAULT_PROJECT_NAME)
|
|
30
31
|
if content_type == "application/x-pandas-arrow":
|
|
31
32
|
return await self._process_pyarrow(request)
|
|
32
33
|
if content_type != "application/x-protobuf":
|
|
@@ -51,7 +52,7 @@ class EvaluationHandler(HTTPEndpoint):
|
|
|
51
52
|
content="Request body is invalid",
|
|
52
53
|
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
|
|
53
54
|
)
|
|
54
|
-
self.traces.put(evaluation)
|
|
55
|
+
self.traces.put(evaluation, project_name=project_name)
|
|
55
56
|
return Response()
|
|
56
57
|
|
|
57
58
|
async def get(self, request: Request) -> Response:
|
|
@@ -7,11 +7,11 @@ from starlette.requests import Request
|
|
|
7
7
|
from starlette.responses import Response, StreamingResponse
|
|
8
8
|
from starlette.status import HTTP_404_NOT_FOUND, HTTP_422_UNPROCESSABLE_ENTITY
|
|
9
9
|
|
|
10
|
+
from phoenix.config import DEFAULT_PROJECT_NAME
|
|
10
11
|
from phoenix.core.traces import Traces
|
|
11
12
|
from phoenix.server.api.routers.utils import df_to_bytes, from_iso_format
|
|
12
13
|
from phoenix.trace.dsl import SpanQuery
|
|
13
14
|
from phoenix.utilities import query_spans
|
|
14
|
-
from phoenix.utilities.project import DEFAULT_PROJECT_NAME
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class SpanHandler(HTTPEndpoint):
|
|
@@ -14,7 +14,7 @@ from starlette.responses import Response
|
|
|
14
14
|
from starlette.status import HTTP_415_UNSUPPORTED_MEDIA_TYPE, HTTP_422_UNPROCESSABLE_ENTITY
|
|
15
15
|
|
|
16
16
|
from phoenix.core.traces import Traces
|
|
17
|
-
from phoenix.storage.
|
|
17
|
+
from phoenix.storage.span_store import SpanStore
|
|
18
18
|
from phoenix.trace.otel import decode
|
|
19
19
|
from phoenix.utilities.project import get_project_name
|
|
20
20
|
|
phoenix/server/api/schema.py
CHANGED
|
@@ -56,8 +56,8 @@ class Query:
|
|
|
56
56
|
[]
|
|
57
57
|
if (traces := info.context.traces) is None
|
|
58
58
|
else [
|
|
59
|
-
Project(id_attr=
|
|
60
|
-
for
|
|
59
|
+
Project(id_attr=project_id, name=project_name, project=project)
|
|
60
|
+
for project_id, project_name, project in traces.get_projects()
|
|
61
61
|
]
|
|
62
62
|
)
|
|
63
63
|
return connection_from_list(data=data, args=args)
|
|
@@ -86,8 +86,11 @@ class Query:
|
|
|
86
86
|
return to_gql_embedding_dimension(node_id, embedding_dimension)
|
|
87
87
|
elif type_name == "Project":
|
|
88
88
|
if (traces := info.context.traces) is not None:
|
|
89
|
-
projects =
|
|
90
|
-
|
|
89
|
+
projects = {
|
|
90
|
+
project_id: (project_name, project)
|
|
91
|
+
for project_id, project_name, project in traces.get_projects()
|
|
92
|
+
}
|
|
93
|
+
if node_id in projects:
|
|
91
94
|
name, project = projects[node_id]
|
|
92
95
|
return Project(id_attr=node_id, name=name, project=project)
|
|
93
96
|
raise Exception(f"Unknown project: {id}")
|
|
@@ -224,7 +227,26 @@ class Query:
|
|
|
224
227
|
|
|
225
228
|
|
|
226
229
|
@strawberry.type
|
|
227
|
-
class Mutation(ExportEventsMutation):
|
|
230
|
+
class Mutation(ExportEventsMutation):
|
|
231
|
+
@strawberry.mutation
|
|
232
|
+
def delete_project(self, info: Info[Context, None], id: GlobalID) -> Query:
|
|
233
|
+
if (traces := info.context.traces) is None:
|
|
234
|
+
return Query()
|
|
235
|
+
type_name, node_id = from_global_id(str(id))
|
|
236
|
+
if type_name != "Project":
|
|
237
|
+
return Query()
|
|
238
|
+
traces.archive_project(node_id)
|
|
239
|
+
return Query()
|
|
240
|
+
|
|
241
|
+
@strawberry.mutation
|
|
242
|
+
def archive_project(self, info: Info[Context, None], id: GlobalID) -> Query:
|
|
243
|
+
if (traces := info.context.traces) is None:
|
|
244
|
+
return Query()
|
|
245
|
+
type_name, node_id = from_global_id(str(id))
|
|
246
|
+
if type_name != "Project":
|
|
247
|
+
return Query()
|
|
248
|
+
traces.archive_project(node_id)
|
|
249
|
+
return Query()
|
|
228
250
|
|
|
229
251
|
|
|
230
252
|
schema = strawberry.Schema(query=Query, mutation=Mutation)
|
phoenix/server/api/types/Span.py
CHANGED
|
@@ -4,12 +4,14 @@ from datetime import datetime
|
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from typing import Any, DefaultDict, Dict, List, Mapping, Optional, Sized, cast
|
|
6
6
|
|
|
7
|
+
import numpy as np
|
|
7
8
|
import strawberry
|
|
8
9
|
from openinference.semconv.trace import EmbeddingAttributes, SpanAttributes
|
|
9
10
|
from strawberry import ID, UNSET
|
|
10
11
|
from strawberry.types import Info
|
|
11
12
|
|
|
12
13
|
import phoenix.trace.schemas as trace_schema
|
|
14
|
+
from phoenix.config import DEFAULT_PROJECT_NAME
|
|
13
15
|
from phoenix.core.project import Project, WrappedSpan
|
|
14
16
|
from phoenix.metrics.retrieval_metrics import RetrievalMetrics
|
|
15
17
|
from phoenix.server.api.context import Context
|
|
@@ -17,7 +19,6 @@ from phoenix.server.api.types.DocumentRetrievalMetrics import DocumentRetrievalM
|
|
|
17
19
|
from phoenix.server.api.types.Evaluation import DocumentEvaluation, SpanEvaluation
|
|
18
20
|
from phoenix.server.api.types.MimeType import MimeType
|
|
19
21
|
from phoenix.trace.schemas import ComputedAttributes, SpanID
|
|
20
|
-
from phoenix.utilities.project import DEFAULT_PROJECT_NAME
|
|
21
22
|
|
|
22
23
|
EMBEDDING_EMBEDDINGS = SpanAttributes.EMBEDDING_EMBEDDINGS
|
|
23
24
|
EMBEDDING_VECTOR = EmbeddingAttributes.EMBEDDING_VECTOR
|
|
@@ -249,7 +250,7 @@ def to_gql_span(span: WrappedSpan, project: Project) -> "Span":
|
|
|
249
250
|
),
|
|
250
251
|
attributes=json.dumps(
|
|
251
252
|
_nested_attributes(_hide_embedding_vectors(span.attributes)),
|
|
252
|
-
|
|
253
|
+
cls=_JSONEncoder,
|
|
253
254
|
),
|
|
254
255
|
metadata=_convert_metadata_to_string(span.attributes.get(METADATA)),
|
|
255
256
|
num_documents=num_documents,
|
|
@@ -302,10 +303,19 @@ def to_gql_span(span: WrappedSpan, project: Project) -> "Span":
|
|
|
302
303
|
)
|
|
303
304
|
|
|
304
305
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
306
|
+
class _JSONEncoder(json.JSONEncoder):
|
|
307
|
+
def default(self, obj: Any) -> Any:
|
|
308
|
+
if isinstance(obj, datetime):
|
|
309
|
+
return obj.isoformat()
|
|
310
|
+
if isinstance(obj, Enum):
|
|
311
|
+
return obj.value
|
|
312
|
+
if isinstance(obj, np.ndarray):
|
|
313
|
+
return list(obj)
|
|
314
|
+
if isinstance(obj, np.integer):
|
|
315
|
+
return int(obj)
|
|
316
|
+
if isinstance(obj, np.floating):
|
|
317
|
+
return float(obj)
|
|
318
|
+
return super().default(obj)
|
|
309
319
|
|
|
310
320
|
|
|
311
321
|
def _trie() -> DefaultDict[str, Any]:
|
phoenix/server/app.py
CHANGED
|
@@ -28,7 +28,7 @@ from phoenix.server.api.routers.evaluation_handler import EvaluationHandler
|
|
|
28
28
|
from phoenix.server.api.routers.span_handler import SpanHandler
|
|
29
29
|
from phoenix.server.api.routers.trace_handler import TraceHandler
|
|
30
30
|
from phoenix.server.api.schema import schema
|
|
31
|
-
from phoenix.storage.
|
|
31
|
+
from phoenix.storage.span_store import SpanStore
|
|
32
32
|
|
|
33
33
|
logger = logging.getLogger(__name__)
|
|
34
34
|
|
phoenix/server/main.py
CHANGED
|
@@ -16,7 +16,6 @@ from phoenix.config import (
|
|
|
16
16
|
get_env_host,
|
|
17
17
|
get_env_port,
|
|
18
18
|
get_pids_path,
|
|
19
|
-
get_storage_dir,
|
|
20
19
|
)
|
|
21
20
|
from phoenix.core.model_schema_adapter import create_model_from_datasets
|
|
22
21
|
from phoenix.core.traces import Traces
|
|
@@ -29,8 +28,7 @@ from phoenix.pointcloud.umap_parameters import (
|
|
|
29
28
|
UMAPParameters,
|
|
30
29
|
)
|
|
31
30
|
from phoenix.server.app import create_app
|
|
32
|
-
from phoenix.storage.
|
|
33
|
-
from phoenix.storage.spanstore.text_file import TextFileSpanStoreImpl
|
|
31
|
+
from phoenix.storage.span_store import SpanStore
|
|
34
32
|
from phoenix.trace.fixtures import (
|
|
35
33
|
TRACES_FIXTURES,
|
|
36
34
|
_download_traces_fixture,
|
|
@@ -39,7 +37,7 @@ from phoenix.trace.fixtures import (
|
|
|
39
37
|
)
|
|
40
38
|
from phoenix.trace.otel import decode, encode
|
|
41
39
|
from phoenix.trace.span_json_decoder import json_string_to_span
|
|
42
|
-
from phoenix.utilities.
|
|
40
|
+
from phoenix.utilities.span_store import get_span_store, load_traces_data_from_store
|
|
43
41
|
|
|
44
42
|
logger = logging.getLogger(__name__)
|
|
45
43
|
|
|
@@ -108,15 +106,6 @@ def _load_items(
|
|
|
108
106
|
queue.put(item)
|
|
109
107
|
|
|
110
108
|
|
|
111
|
-
def _load_from_store(traces: Traces, span_store: SpanStore) -> None:
|
|
112
|
-
for traces_data in span_store.load():
|
|
113
|
-
for resource_spans in traces_data.resource_spans:
|
|
114
|
-
project_name = get_project_name(resource_spans.resource.attributes)
|
|
115
|
-
for scope_span in resource_spans.scope_spans:
|
|
116
|
-
for span in scope_span.spans:
|
|
117
|
-
traces.put(decode(span), project_name=project_name)
|
|
118
|
-
|
|
119
|
-
|
|
120
109
|
DEFAULT_UMAP_PARAMS_STR = f"{DEFAULT_MIN_DIST},{DEFAULT_N_NEIGHBORS},{DEFAULT_N_SAMPLES}"
|
|
121
110
|
|
|
122
111
|
if __name__ == "__main__":
|
|
@@ -142,8 +131,6 @@ if __name__ == "__main__":
|
|
|
142
131
|
parser.add_argument("--debug", action="store_false")
|
|
143
132
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
144
133
|
serve_parser = subparsers.add_parser("serve")
|
|
145
|
-
experimental_parser = subparsers.add_parser("extremely-dangerous-experimental-span-storage")
|
|
146
|
-
experimental_parser.add_argument("--storage-path", type=str, required=False)
|
|
147
134
|
datasets_parser = subparsers.add_parser("datasets")
|
|
148
135
|
datasets_parser.add_argument("--primary", type=str, required=True)
|
|
149
136
|
datasets_parser.add_argument("--reference", type=str, required=False)
|
|
@@ -200,19 +187,14 @@ if __name__ == "__main__":
|
|
|
200
187
|
)
|
|
201
188
|
trace_dataset_name = args.trace_fixture
|
|
202
189
|
simulate_streaming = args.simulate_streaming
|
|
203
|
-
elif args.command == "extremely-dangerous-experimental-span-storage":
|
|
204
|
-
span_store_path = (
|
|
205
|
-
get_storage_dir() if args.storage_path is None else Path(args.storage_path)
|
|
206
|
-
)
|
|
207
|
-
span_store = TextFileSpanStoreImpl(span_store_path)
|
|
208
190
|
|
|
209
191
|
model = create_model_from_datasets(
|
|
210
192
|
primary_dataset,
|
|
211
193
|
reference_dataset,
|
|
212
194
|
)
|
|
213
195
|
traces = Traces()
|
|
214
|
-
if span_store:
|
|
215
|
-
Thread(target=
|
|
196
|
+
if span_store := get_span_store():
|
|
197
|
+
Thread(target=load_traces_data_from_store, args=(traces, span_store), daemon=True).start()
|
|
216
198
|
if trace_dataset_name is not None:
|
|
217
199
|
fixture_spans = list(
|
|
218
200
|
# Apply `encode` here because legacy jsonl files contains UUIDs as strings.
|