arize-phoenix 4.30.2__py3-none-any.whl → 4.32.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.30.2.dist-info → arize_phoenix-4.32.0.dist-info}/METADATA +6 -8
- {arize_phoenix-4.30.2.dist-info → arize_phoenix-4.32.0.dist-info}/RECORD +20 -20
- phoenix/config.py +10 -0
- phoenix/server/app.py +74 -34
- phoenix/server/dml_event_handler.py +1 -0
- phoenix/server/main.py +33 -6
- phoenix/server/static/.vite/manifest.json +31 -31
- phoenix/server/static/assets/{components-CkSg5zK4.js → components-Ddr-5VpM.js} +46 -46
- phoenix/server/static/assets/index-BvNNAF8n.js +100 -0
- phoenix/server/static/assets/{pages-C6emDFIO.js → pages-CU_QMYRP.js} +309 -232
- phoenix/server/static/assets/{vendor-DsnEJuEV.js → vendor-Dpio9q2e.js} +1 -1
- phoenix/server/static/assets/{vendor-arizeai-DtynTLNi.js → vendor-arizeai-DDzwX9A6.js} +24 -24
- phoenix/server/static/assets/{vendor-codemirror-C5to5cK4.js → vendor-codemirror-xRvQKK1G.js} +1 -1
- phoenix/server/static/assets/{vendor-recharts-reihe2SJ.js → vendor-recharts-DoxlB_Wo.js} +1 -1
- phoenix/trace/fixtures.py +46 -10
- phoenix/trace/utils.py +2 -8
- phoenix/version.py +1 -1
- phoenix/server/static/assets/index-DTecsU5w.js +0 -100
- {arize_phoenix-4.30.2.dist-info → arize_phoenix-4.32.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.30.2.dist-info → arize_phoenix-4.32.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.30.2.dist-info → arize_phoenix-4.32.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: arize-phoenix
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.32.0
|
|
4
4
|
Summary: AI Observability and Evaluation
|
|
5
5
|
Project-URL: Documentation, https://docs.arize.com/phoenix/
|
|
6
6
|
Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
|
|
@@ -99,7 +99,10 @@ Requires-Dist: pytest==8.3.2; extra == 'dev'
|
|
|
99
99
|
Requires-Dist: ruff==0.6.1; extra == 'dev'
|
|
100
100
|
Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.236.0; extra == 'dev'
|
|
101
101
|
Requires-Dist: tabulate; extra == 'dev'
|
|
102
|
+
Requires-Dist: tox; extra == 'dev'
|
|
103
|
+
Requires-Dist: tox-uv; extra == 'dev'
|
|
102
104
|
Requires-Dist: types-tabulate; extra == 'dev'
|
|
105
|
+
Requires-Dist: uv; extra == 'dev'
|
|
103
106
|
Requires-Dist: uvloop; (platform_system != 'Windows') and extra == 'dev'
|
|
104
107
|
Provides-Extra: evals
|
|
105
108
|
Provides-Extra: experimental
|
|
@@ -157,10 +160,10 @@ Phoenix runs practically anywhere, including your Jupyter notebook, local machin
|
|
|
157
160
|
|
|
158
161
|
## Installation
|
|
159
162
|
|
|
160
|
-
Install Phoenix via `pip` or `conda`
|
|
163
|
+
Install Phoenix via `pip` or `conda`
|
|
161
164
|
|
|
162
165
|
```shell
|
|
163
|
-
pip install
|
|
166
|
+
pip install arize-phoenix
|
|
164
167
|
```
|
|
165
168
|
|
|
166
169
|
Phoenix container images are available via [Docker Hub](https://hub.docker.com/r/arizephoenix/phoenix) and can be deployed using Docker or Kubernetes.
|
|
@@ -177,11 +180,6 @@ Join our community to connect with thousands of AI builders.
|
|
|
177
180
|
- 💌️ Sign up for our [mailing list](https://phoenix.arize.com/#updates).
|
|
178
181
|
- 🗺️ Check out our [roadmap](https://github.com/orgs/Arize-ai/projects/45) to see where we're heading next.
|
|
179
182
|
|
|
180
|
-
## Thanks
|
|
181
|
-
|
|
182
|
-
- [UMAP](https://github.com/lmcinnes/umap) For unlocking the ability to visualize and reason about embeddings
|
|
183
|
-
- [HDBSCAN](https://github.com/scikit-learn-contrib/hdbscan) For providing a clustering algorithm to aid in the discovery of drift and performance degradation
|
|
184
|
-
|
|
185
183
|
## Breaking Changes
|
|
186
184
|
|
|
187
185
|
See the [migration guide](./MIGRATION.md) for a list of breaking changes.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
phoenix/__init__.py,sha256=TGNWqm2UW-l67yIRpOtmqGHVAmdoobSNqUsiTtip7uQ,1542
|
|
2
2
|
phoenix/auth.py,sha256=ugvGZlseYX9NkpWaSqb8D2kzUBlAPqT45Dx5_VUANqk,1621
|
|
3
|
-
phoenix/config.py,sha256=
|
|
3
|
+
phoenix/config.py,sha256=RfS-0kzEOhirX9EmVMr8cu7qCDtkq8HpxhhctEgh0Yo,10795
|
|
4
4
|
phoenix/datetime_utils.py,sha256=yDKjwX2Vtqw9h5F_ProtP-TsXidM43uIvmJ_pOzYc9A,3405
|
|
5
5
|
phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
7
|
phoenix/services.py,sha256=OyML4t2XGnlqF0JXA9_uccL8HslTABxep9Ci7MViKEU,5216
|
|
8
8
|
phoenix/settings.py,sha256=cO-qgis_S27nHirTobYI9hHPfZH18R--WMmxNdsVUwc,273
|
|
9
|
-
phoenix/version.py,sha256=
|
|
9
|
+
phoenix/version.py,sha256=_QUskFVbFLd7O3BXo2PEGlMc717xpkYLlK-r6lVv4_I,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=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
|
|
@@ -72,11 +72,11 @@ phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYG
|
|
|
72
72
|
phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
|
|
73
73
|
phoenix/pointcloud/umap_parameters.py,sha256=3UQSjrysVOvq2V4KNpTMqNqNiK0BsTZnPBHWZ4fyJtQ,1708
|
|
74
74
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
phoenix/server/app.py,sha256=
|
|
75
|
+
phoenix/server/app.py,sha256=i5VhDdqPoQ8i5WlwjnUZAjedx8xOiL16R2OzATg9LQE,28333
|
|
76
76
|
phoenix/server/dml_event.py,sha256=MpjCFqljxvgb9OB5Cez9vJesb3oHb3XxXictynBfcis,2851
|
|
77
|
-
phoenix/server/dml_event_handler.py,sha256=
|
|
77
|
+
phoenix/server/dml_event_handler.py,sha256=yU23-DDwXcL35p5EPwFW0oZh6mxQxJrJAQPKcYZYJz4,8310
|
|
78
78
|
phoenix/server/grpc_server.py,sha256=jllxDNkpLQxDkvej4RhTokobowbvydF-SU8gSw1MTCc,3378
|
|
79
|
-
phoenix/server/main.py,sha256=
|
|
79
|
+
phoenix/server/main.py,sha256=FnETeVWwcsnA4z67gHE9Br8BUCmW8cMQC-YpjCq-Zz0,14634
|
|
80
80
|
phoenix/server/prometheus.py,sha256=j9DHB2fERuq_ZKmwVaqR-9wx5WcPPuU1Cm5Bhg5241Y,2996
|
|
81
81
|
phoenix/server/telemetry.py,sha256=T_2OKrxNViAeaANlNspEekg_Y5uZIFWvKAnpz8Aoqvk,2762
|
|
82
82
|
phoenix/server/thread_server.py,sha256=RwXQGP_QhGD7le6WB7xEygEEuwBl5Ck_Zo8xGIYGi9M,2135
|
|
@@ -242,15 +242,15 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
242
242
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
243
243
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
244
244
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
245
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
246
|
-
phoenix/server/static/assets/components-
|
|
247
|
-
phoenix/server/static/assets/index-
|
|
248
|
-
phoenix/server/static/assets/pages-
|
|
249
|
-
phoenix/server/static/assets/vendor-
|
|
245
|
+
phoenix/server/static/.vite/manifest.json,sha256=2equEiHXZGCivKbAQc9U9NATOUVltsQoiM0lhdD4TZE,1929
|
|
246
|
+
phoenix/server/static/assets/components-Ddr-5VpM.js,sha256=kKqWpR-S-axVFd3tD_bfc3OD9HEleq0Pdn_cofQuzDo,244415
|
|
247
|
+
phoenix/server/static/assets/index-BvNNAF8n.js,sha256=-keFoN2koW7IT6Iv_kbUpDDqv-TkpjSccukpYvuI8yo,7602
|
|
248
|
+
phoenix/server/static/assets/pages-CU_QMYRP.js,sha256=iiwCelLTc7KsQeRr5mRW0lnDd8fNFPwWo4NjSKp6J2A,511373
|
|
249
|
+
phoenix/server/static/assets/vendor-Dpio9q2e.js,sha256=1CMQ_vGa7qQyJoLj1WdL23CVQ6y9E94cv1cy_KHNi84,1435263
|
|
250
250
|
phoenix/server/static/assets/vendor-DxkFTwjz.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
|
|
251
|
-
phoenix/server/static/assets/vendor-arizeai-
|
|
252
|
-
phoenix/server/static/assets/vendor-codemirror-
|
|
253
|
-
phoenix/server/static/assets/vendor-recharts-
|
|
251
|
+
phoenix/server/static/assets/vendor-arizeai-DDzwX9A6.js,sha256=ePHP1b8n-zwCMGEwgfR00aOTSEe8Ogp8gx3FyZ1-SyA,304401
|
|
252
|
+
phoenix/server/static/assets/vendor-codemirror-xRvQKK1G.js,sha256=frhtxbn75y5RLIBSiyAsc5p9Vf8eZgLMaBmTau7-fgU,516470
|
|
253
|
+
phoenix/server/static/assets/vendor-recharts-DoxlB_Wo.js,sha256=kwD-Sn947JKsQjfpH3ybD-O1F-Qvner2KUP9a5Naqbs,282859
|
|
254
254
|
phoenix/server/static/assets/vendor-three-DwGkEfCM.js,sha256=0D12ZgKzfKCTSdSTKJBFR2RZO_xxeMXrqDp0AszZqHY,620972
|
|
255
255
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
256
256
|
phoenix/server/templates/index.html,sha256=dAm0IClgJUdT5AOmjZvtgMg8F_xGrRGv95SAkUyx_kg,4325
|
|
@@ -264,7 +264,7 @@ phoenix/trace/attributes.py,sha256=B_OrzVaxZwFkrAFXZyicYoIti1UdUysURsvUS2GyW1U,1
|
|
|
264
264
|
phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
|
|
265
265
|
phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
|
|
266
266
|
phoenix/trace/exporter.py,sha256=eAYemdvDCHMugDJiaR29BFFMTQBdf3oerdkz34Cl3hE,4736
|
|
267
|
-
phoenix/trace/fixtures.py,sha256=
|
|
267
|
+
phoenix/trace/fixtures.py,sha256=YsKJJEnqo1f_yJzVrfQnnrmS0LlQl7k37lbLY2pZ7ds,17856
|
|
268
268
|
phoenix/trace/otel.py,sha256=WA720jvRadiZBAKjsYoPyXzypHwbyEK2OZRVUwtbjB8,9976
|
|
269
269
|
phoenix/trace/projects.py,sha256=2BwlNjFE-uwpqYtCu5YyBiYZk9wRPpM13vh3-Cv7GkA,2157
|
|
270
270
|
phoenix/trace/schemas.py,sha256=HpWSyzec0yDHEQXEDuwyLbhpvKrqkGps8BJqGiIFj8Y,5978
|
|
@@ -272,7 +272,7 @@ phoenix/trace/span_evaluations.py,sha256=GaADtJLi2njra4aYaie0BIwkSgdxPB_SNseglI4
|
|
|
272
272
|
phoenix/trace/span_json_decoder.py,sha256=jkpYSmOUsSptvahOvetrPjVkPIuI4h6b87eizL8wHp8,3230
|
|
273
273
|
phoenix/trace/span_json_encoder.py,sha256=tzSCIQJbeFBm33K68G8A5M12n_86tCDyuU0WAobxEz4,2010
|
|
274
274
|
phoenix/trace/trace_dataset.py,sha256=Wq89jJ4hYQ1Qt-Uj11ZNzKQYQeKmGY6NqWStQiiTlMw,14351
|
|
275
|
-
phoenix/trace/utils.py,sha256=
|
|
275
|
+
phoenix/trace/utils.py,sha256=lWinMM7Tsq_DCsBD5Ck97lxouBHrY4muGNsh8JD3qg4,1694
|
|
276
276
|
phoenix/trace/dsl/README.md,sha256=ihmP9zGUC5V-TDbzKla76LuyDqPDQIBUH2BORwxNI68,2902
|
|
277
277
|
phoenix/trace/dsl/__init__.py,sha256=WIQIjJg362XD3s50OsPJJ0xbDsGp41bSv7vDllLrPuA,144
|
|
278
278
|
phoenix/trace/dsl/filter.py,sha256=9NwATCUOgJ4Pms8XsEcinROUuxZ9UW-ISV09o65Ms70,32600
|
|
@@ -296,8 +296,8 @@ phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,
|
|
|
296
296
|
phoenix/utilities/project.py,sha256=8IJuMM4yUMoooPi37sictGj8Etu9rGmq6RFtc9848cQ,436
|
|
297
297
|
phoenix/utilities/re.py,sha256=PDve_OLjRTM8yQQJHC8-n3HdIONi7aNils3ZKRZ5uBM,2045
|
|
298
298
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
299
|
-
arize_phoenix-4.
|
|
300
|
-
arize_phoenix-4.
|
|
301
|
-
arize_phoenix-4.
|
|
302
|
-
arize_phoenix-4.
|
|
303
|
-
arize_phoenix-4.
|
|
299
|
+
arize_phoenix-4.32.0.dist-info/METADATA,sha256=h2RQifXqJMNa4wFC16Cz8CsS4H_rRUxrmnb_tta0lmY,11741
|
|
300
|
+
arize_phoenix-4.32.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
301
|
+
arize_phoenix-4.32.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
302
|
+
arize_phoenix-4.32.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
303
|
+
arize_phoenix-4.32.0.dist-info/RECORD,,
|
phoenix/config.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
import tempfile
|
|
3
4
|
from logging import getLogger
|
|
4
5
|
from pathlib import Path
|
|
@@ -231,6 +232,14 @@ def get_env_port() -> int:
|
|
|
231
232
|
return PORT
|
|
232
233
|
if port.isnumeric():
|
|
233
234
|
return int(port)
|
|
235
|
+
if _KUBERNETES_PHOENIX_PORT_PATTERN.match(port) is not None:
|
|
236
|
+
raise ValueError(
|
|
237
|
+
'If you are deploying Phoenix with Kubernetes using a service named "phoenix", '
|
|
238
|
+
"Kubernetes will automatically generate an environment variable `PHOENIX_PORT` "
|
|
239
|
+
'of the form "tcp://<IP>:<PORT>" that is not the integer format Phoenix expects. '
|
|
240
|
+
"To resolve this issue, explicitly set the `PHOENIX_PORT` environment variable to "
|
|
241
|
+
"an integer value in your Kubernetes deployment configuration."
|
|
242
|
+
)
|
|
234
243
|
raise ValueError(
|
|
235
244
|
f"Invalid value for environment variable {ENV_PHOENIX_PORT}: "
|
|
236
245
|
f"{port}. Value must be an integer."
|
|
@@ -313,3 +322,4 @@ def get_web_base_url() -> str:
|
|
|
313
322
|
|
|
314
323
|
|
|
315
324
|
DEFAULT_PROJECT_NAME = "default"
|
|
325
|
+
_KUBERNETES_PHOENIX_PORT_PATTERN = re.compile(r"^tcp://\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}:\d+$")
|
phoenix/server/app.py
CHANGED
|
@@ -2,6 +2,8 @@ import asyncio
|
|
|
2
2
|
import contextlib
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
|
+
from contextlib import AsyncExitStack
|
|
6
|
+
from dataclasses import dataclass, field
|
|
5
7
|
from datetime import datetime, timedelta, timezone
|
|
6
8
|
from functools import cached_property
|
|
7
9
|
from pathlib import Path
|
|
@@ -18,7 +20,6 @@ from typing import (
|
|
|
18
20
|
List,
|
|
19
21
|
NamedTuple,
|
|
20
22
|
Optional,
|
|
21
|
-
Set,
|
|
22
23
|
Tuple,
|
|
23
24
|
Union,
|
|
24
25
|
cast,
|
|
@@ -46,7 +47,13 @@ from typing_extensions import TypeAlias
|
|
|
46
47
|
|
|
47
48
|
import phoenix
|
|
48
49
|
import phoenix.trace.v1 as pb
|
|
49
|
-
from phoenix.config import
|
|
50
|
+
from phoenix.config import (
|
|
51
|
+
DEFAULT_PROJECT_NAME,
|
|
52
|
+
SERVER_DIR,
|
|
53
|
+
get_env_host,
|
|
54
|
+
get_env_port,
|
|
55
|
+
server_instrumentation_is_enabled,
|
|
56
|
+
)
|
|
50
57
|
from phoenix.core.model_schema import Model
|
|
51
58
|
from phoenix.db import models
|
|
52
59
|
from phoenix.db.bulk_inserter import BulkInserter
|
|
@@ -95,10 +102,13 @@ from phoenix.server.types import (
|
|
|
95
102
|
LastUpdatedAt,
|
|
96
103
|
)
|
|
97
104
|
from phoenix.trace.fixtures import (
|
|
105
|
+
TracesFixture,
|
|
106
|
+
get_dataset_fixtures,
|
|
98
107
|
get_evals_from_fixture,
|
|
99
108
|
get_trace_fixture_by_name,
|
|
100
109
|
load_example_traces,
|
|
101
110
|
reset_fixture_span_ids_and_timestamps,
|
|
111
|
+
send_dataset_fixtures,
|
|
102
112
|
)
|
|
103
113
|
from phoenix.trace.otel import decode_otlp_span, encode_span_to_otlp
|
|
104
114
|
from phoenix.trace.schemas import Span
|
|
@@ -242,25 +252,36 @@ def _db(engine: AsyncEngine) -> Callable[[], AsyncContextManager[AsyncSession]]:
|
|
|
242
252
|
return factory
|
|
243
253
|
|
|
244
254
|
|
|
255
|
+
@dataclass(frozen=True)
|
|
256
|
+
class ScaffolderConfig:
|
|
257
|
+
db: DbSessionFactory
|
|
258
|
+
tracing_fixture_names: Iterable[str] = field(default_factory=list)
|
|
259
|
+
force_fixture_ingestion: bool = False
|
|
260
|
+
scaffold_datasets: bool = False
|
|
261
|
+
phoenix_url: str = f"http://{get_env_host()}:{get_env_port()}"
|
|
262
|
+
|
|
263
|
+
|
|
245
264
|
class Scaffolder(DaemonTask):
|
|
246
265
|
def __init__(
|
|
247
266
|
self,
|
|
248
|
-
|
|
267
|
+
config: ScaffolderConfig,
|
|
249
268
|
queue_span: Callable[[Span, ProjectName], Awaitable[None]],
|
|
250
269
|
queue_evaluation: Callable[[pb.Evaluation], Awaitable[None]],
|
|
251
|
-
tracing_fixture_names: Set[str] = set(),
|
|
252
|
-
force_fixture_ingestion: bool = False,
|
|
253
270
|
) -> None:
|
|
254
271
|
super().__init__()
|
|
255
|
-
self._db = db
|
|
272
|
+
self._db = config.db
|
|
256
273
|
self._queue_span = queue_span
|
|
257
274
|
self._queue_evaluation = queue_evaluation
|
|
258
|
-
self._tracing_fixtures =
|
|
259
|
-
get_trace_fixture_by_name(name) for name in tracing_fixture_names
|
|
260
|
-
|
|
261
|
-
self._force_fixture_ingestion = force_fixture_ingestion
|
|
275
|
+
self._tracing_fixtures = [
|
|
276
|
+
get_trace_fixture_by_name(name) for name in set(config.tracing_fixture_names)
|
|
277
|
+
]
|
|
278
|
+
self._force_fixture_ingestion = config.force_fixture_ingestion
|
|
279
|
+
self._scaffold_datasets = config.scaffold_datasets
|
|
280
|
+
self._phoenix_url = config.phoenix_url
|
|
262
281
|
|
|
263
282
|
async def __aenter__(self) -> None:
|
|
283
|
+
if not self._tracing_fixtures:
|
|
284
|
+
return
|
|
264
285
|
await self.start()
|
|
265
286
|
|
|
266
287
|
async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
|
|
@@ -272,7 +293,7 @@ class Scaffolder(DaemonTask):
|
|
|
272
293
|
Determines whether to load fixtures and handles them.
|
|
273
294
|
"""
|
|
274
295
|
if await self._should_load_fixtures():
|
|
275
|
-
logger.info("Loading trace fixtures
|
|
296
|
+
logger.info("Loading trace fixtures...")
|
|
276
297
|
await self._handle_tracing_fixtures()
|
|
277
298
|
logger.info("Finished loading fixtures.")
|
|
278
299
|
else:
|
|
@@ -317,6 +338,10 @@ class Scaffolder(DaemonTask):
|
|
|
317
338
|
get_evals_from_fixture(fixture.name),
|
|
318
339
|
)
|
|
319
340
|
|
|
341
|
+
# Ingest dataset fixtures
|
|
342
|
+
if self._scaffold_datasets:
|
|
343
|
+
await self._handle_dataset_fixtures(fixture)
|
|
344
|
+
|
|
320
345
|
project_name = fixture.project_name or fixture.name
|
|
321
346
|
logger.info(f"Loading '{project_name}' fixtures...")
|
|
322
347
|
for span in fixture_spans:
|
|
@@ -331,6 +356,19 @@ class Scaffolder(DaemonTask):
|
|
|
331
356
|
except Exception as e:
|
|
332
357
|
logger.error(f"Unexpected error processing fixture '{fixture.name}': {e}")
|
|
333
358
|
|
|
359
|
+
async def _handle_dataset_fixtures(self, fixture: TracesFixture) -> None:
|
|
360
|
+
loop = asyncio.get_running_loop()
|
|
361
|
+
try:
|
|
362
|
+
dataset_fixtures = await loop.run_in_executor(None, get_dataset_fixtures, fixture.name)
|
|
363
|
+
await loop.run_in_executor(
|
|
364
|
+
None,
|
|
365
|
+
send_dataset_fixtures,
|
|
366
|
+
self._phoenix_url,
|
|
367
|
+
dataset_fixtures,
|
|
368
|
+
)
|
|
369
|
+
except Exception as e:
|
|
370
|
+
logger.error(f"Error processing dataset fixture: {e}")
|
|
371
|
+
|
|
334
372
|
|
|
335
373
|
def _lifespan(
|
|
336
374
|
*,
|
|
@@ -342,30 +380,34 @@ def _lifespan(
|
|
|
342
380
|
startup_callbacks: Iterable[Callable[[], None]] = (),
|
|
343
381
|
shutdown_callbacks: Iterable[Callable[[], None]] = (),
|
|
344
382
|
read_only: bool = False,
|
|
345
|
-
|
|
346
|
-
force_fixture_ingestion: bool = False,
|
|
383
|
+
scaffolder_config: Optional[ScaffolderConfig] = None,
|
|
347
384
|
) -> StatefulLifespan[FastAPI]:
|
|
348
385
|
@contextlib.asynccontextmanager
|
|
349
386
|
async def lifespan(_: FastAPI) -> AsyncIterator[Dict[str, Any]]:
|
|
350
387
|
global DB_MUTEX
|
|
351
388
|
DB_MUTEX = asyncio.Lock() if db.dialect is SupportedSQLDialect.SQLITE else None
|
|
352
|
-
async with
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
389
|
+
async with AsyncExitStack() as stack:
|
|
390
|
+
(
|
|
391
|
+
enqueue,
|
|
392
|
+
queue_span,
|
|
393
|
+
queue_evaluation,
|
|
394
|
+
enqueue_operation,
|
|
395
|
+
) = await stack.enter_async_context(bulk_inserter)
|
|
396
|
+
grpc_server = GrpcServer(
|
|
397
|
+
queue_span,
|
|
398
|
+
disabled=read_only,
|
|
399
|
+
tracer_provider=tracer_provider,
|
|
400
|
+
enable_prometheus=enable_prometheus,
|
|
401
|
+
)
|
|
402
|
+
await stack.enter_async_context(grpc_server)
|
|
403
|
+
await stack.enter_async_context(dml_event_handler)
|
|
404
|
+
if scaffolder_config:
|
|
405
|
+
scaffolder = Scaffolder(
|
|
406
|
+
config=scaffolder_config,
|
|
407
|
+
queue_span=queue_span,
|
|
408
|
+
queue_evaluation=queue_evaluation,
|
|
409
|
+
)
|
|
410
|
+
await stack.enter_async_context(scaffolder)
|
|
369
411
|
for callback in startup_callbacks:
|
|
370
412
|
callback()
|
|
371
413
|
yield {
|
|
@@ -557,8 +599,7 @@ def create_app(
|
|
|
557
599
|
startup_callbacks: Iterable[Callable[[], None]] = (),
|
|
558
600
|
shutdown_callbacks: Iterable[Callable[[], None]] = (),
|
|
559
601
|
secret: Optional[str] = None,
|
|
560
|
-
|
|
561
|
-
force_fixture_ingestion: bool = False,
|
|
602
|
+
scaffolder_config: Optional[ScaffolderConfig] = None,
|
|
562
603
|
) -> FastAPI:
|
|
563
604
|
startup_callbacks_list: List[Callable[[], None]] = list(startup_callbacks)
|
|
564
605
|
shutdown_callbacks_list: List[Callable[[], None]] = list(shutdown_callbacks)
|
|
@@ -644,8 +685,7 @@ def create_app(
|
|
|
644
685
|
enable_prometheus=enable_prometheus,
|
|
645
686
|
shutdown_callbacks=shutdown_callbacks_list,
|
|
646
687
|
startup_callbacks=startup_callbacks_list,
|
|
647
|
-
|
|
648
|
-
force_fixture_ingestion=force_fixture_ingestion,
|
|
688
|
+
scaffolder_config=scaffolder_config,
|
|
649
689
|
),
|
|
650
690
|
middleware=[
|
|
651
691
|
Middleware(HeadersMiddleware),
|
|
@@ -186,6 +186,7 @@ class _AnnotationDmlEventHandler(
|
|
|
186
186
|
async def __call__(self) -> None:
|
|
187
187
|
async with self._db() as session:
|
|
188
188
|
async for row in await session.stream(self._get_stmt()):
|
|
189
|
+
self._last_updated_at.set(Project, row.id)
|
|
189
190
|
if cache := self._cache_for_dataloaders:
|
|
190
191
|
self._clear(cache, row.id, row.name)
|
|
191
192
|
|
phoenix/server/main.py
CHANGED
|
@@ -37,6 +37,7 @@ from phoenix.pointcloud.umap_parameters import (
|
|
|
37
37
|
UMAPParameters,
|
|
38
38
|
)
|
|
39
39
|
from phoenix.server.app import (
|
|
40
|
+
ScaffolderConfig,
|
|
40
41
|
_db,
|
|
41
42
|
create_app,
|
|
42
43
|
create_engine_and_run_migrations,
|
|
@@ -143,7 +144,9 @@ if __name__ == "__main__":
|
|
|
143
144
|
# Whether the app is running in a development environment
|
|
144
145
|
parser.add_argument("--dev", action="store_true")
|
|
145
146
|
parser.add_argument("--no-ui", action="store_true")
|
|
147
|
+
|
|
146
148
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
149
|
+
|
|
147
150
|
serve_parser = subparsers.add_parser("serve")
|
|
148
151
|
serve_parser.add_argument(
|
|
149
152
|
"--with-fixture",
|
|
@@ -182,14 +185,27 @@ if __name__ == "__main__":
|
|
|
182
185
|
"database is new."
|
|
183
186
|
),
|
|
184
187
|
)
|
|
188
|
+
serve_parser.add_argument(
|
|
189
|
+
"--scaffold-datasets",
|
|
190
|
+
action="store_true", # default is False
|
|
191
|
+
required=False,
|
|
192
|
+
help=(
|
|
193
|
+
"Whether or not to add any datasets defined in "
|
|
194
|
+
"the inputted project or trace fixture. "
|
|
195
|
+
"Default is False. "
|
|
196
|
+
),
|
|
197
|
+
)
|
|
198
|
+
|
|
185
199
|
datasets_parser = subparsers.add_parser("datasets")
|
|
186
200
|
datasets_parser.add_argument("--primary", type=str, required=True)
|
|
187
201
|
datasets_parser.add_argument("--reference", type=str, required=False)
|
|
188
202
|
datasets_parser.add_argument("--corpus", type=str, required=False)
|
|
189
203
|
datasets_parser.add_argument("--trace", type=str, required=False)
|
|
204
|
+
|
|
190
205
|
fixture_parser = subparsers.add_parser("fixture")
|
|
191
206
|
fixture_parser.add_argument("fixture", type=str, choices=[fixture.name for fixture in FIXTURES])
|
|
192
207
|
fixture_parser.add_argument("--primary-only", action="store_true") # Default is False
|
|
208
|
+
|
|
193
209
|
trace_fixture_parser = subparsers.add_parser("trace-fixture")
|
|
194
210
|
trace_fixture_parser.add_argument(
|
|
195
211
|
"fixture", type=str, choices=[fixture.name for fixture in TRACES_FIXTURES]
|
|
@@ -197,19 +213,23 @@ if __name__ == "__main__":
|
|
|
197
213
|
trace_fixture_parser.add_argument(
|
|
198
214
|
"--simulate-streaming", action="store_true"
|
|
199
215
|
) # Default is False
|
|
216
|
+
|
|
200
217
|
demo_parser = subparsers.add_parser("demo")
|
|
201
218
|
demo_parser.add_argument("fixture", type=str, choices=[fixture.name for fixture in FIXTURES])
|
|
202
219
|
demo_parser.add_argument(
|
|
203
220
|
"trace_fixture", type=str, choices=[fixture.name for fixture in TRACES_FIXTURES]
|
|
204
221
|
)
|
|
205
222
|
demo_parser.add_argument("--simulate-streaming", action="store_true")
|
|
206
|
-
args = parser.parse_args()
|
|
207
223
|
|
|
224
|
+
args = parser.parse_args()
|
|
208
225
|
db_connection_str = (
|
|
209
226
|
args.database_url if args.database_url else get_env_database_connection_str()
|
|
210
227
|
)
|
|
211
228
|
export_path = Path(args.export_path) if args.export_path else EXPORT_DIR
|
|
229
|
+
|
|
212
230
|
force_fixture_ingestion = False
|
|
231
|
+
scaffold_datasets = False
|
|
232
|
+
tracing_fixture_names = set()
|
|
213
233
|
if args.command == "datasets":
|
|
214
234
|
primary_inferences_name = args.primary
|
|
215
235
|
reference_inferences_name = args.reference
|
|
@@ -246,7 +266,6 @@ if __name__ == "__main__":
|
|
|
246
266
|
simulate_streaming = args.simulate_streaming
|
|
247
267
|
elif args.command == "serve":
|
|
248
268
|
# We use sets to avoid duplicates
|
|
249
|
-
tracing_fixture_names = set()
|
|
250
269
|
if args.with_fixture:
|
|
251
270
|
primary_inferences, reference_inferences, corpus_inferences = get_inferences(
|
|
252
271
|
str(args.with_fixture),
|
|
@@ -264,6 +283,7 @@ if __name__ == "__main__":
|
|
|
264
283
|
for fixture in get_trace_fixtures_by_project_name(name)
|
|
265
284
|
)
|
|
266
285
|
force_fixture_ingestion = args.force_fixture_ingestion
|
|
286
|
+
scaffold_datasets = args.scaffold_datasets
|
|
267
287
|
host: Optional[str] = args.host or get_env_host()
|
|
268
288
|
display_host = host or "localhost"
|
|
269
289
|
# If the host is "::", the convention is to bind to all interfaces. However, uvicorn
|
|
@@ -325,17 +345,25 @@ if __name__ == "__main__":
|
|
|
325
345
|
None if corpus_inferences is None else create_model_from_inferences(corpus_inferences)
|
|
326
346
|
)
|
|
327
347
|
# Print information about the server
|
|
348
|
+
root_path = urljoin(f"http://{host}:{port}", host_root_path)
|
|
328
349
|
msg = _WELCOME_MESSAGE.format(
|
|
329
350
|
version=version("arize-phoenix"),
|
|
330
|
-
ui_path=
|
|
351
|
+
ui_path=root_path,
|
|
331
352
|
grpc_path=f"http://{host}:{get_env_grpc_port()}",
|
|
332
|
-
http_path=urljoin(
|
|
353
|
+
http_path=urljoin(root_path, "v1/traces"),
|
|
333
354
|
storage=get_printable_db_url(db_connection_str),
|
|
334
355
|
)
|
|
335
356
|
if authentication_enabled:
|
|
336
357
|
msg += _EXPERIMENTAL_WARNING.format(auth_enabled=True)
|
|
337
358
|
if sys.platform.startswith("win"):
|
|
338
359
|
msg = codecs.encode(msg, "ascii", errors="ignore").decode("ascii").strip()
|
|
360
|
+
scaffolder_config = ScaffolderConfig(
|
|
361
|
+
db=factory,
|
|
362
|
+
tracing_fixture_names=tracing_fixture_names,
|
|
363
|
+
force_fixture_ingestion=force_fixture_ingestion,
|
|
364
|
+
scaffold_datasets=scaffold_datasets,
|
|
365
|
+
phoenix_url=root_path,
|
|
366
|
+
)
|
|
339
367
|
app = create_app(
|
|
340
368
|
db=factory,
|
|
341
369
|
export_path=export_path,
|
|
@@ -353,8 +381,7 @@ if __name__ == "__main__":
|
|
|
353
381
|
startup_callbacks=[lambda: print(msg)],
|
|
354
382
|
shutdown_callbacks=instrumentation_cleanups,
|
|
355
383
|
secret=secret,
|
|
356
|
-
|
|
357
|
-
force_fixture_ingestion=force_fixture_ingestion,
|
|
384
|
+
scaffolder_config=scaffolder_config,
|
|
358
385
|
)
|
|
359
386
|
server = Server(config=Config(app, host=host, port=port, root_path=host_root_path)) # type: ignore
|
|
360
387
|
Thread(target=_write_pid_file_when_ready, args=(server,), daemon=True).start()
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_components-
|
|
3
|
-
"file": "assets/components-
|
|
2
|
+
"_components-Ddr-5VpM.js": {
|
|
3
|
+
"file": "assets/components-Ddr-5VpM.js",
|
|
4
4
|
"name": "components",
|
|
5
5
|
"imports": [
|
|
6
|
-
"_vendor-
|
|
7
|
-
"_vendor-arizeai-
|
|
8
|
-
"_pages-
|
|
6
|
+
"_vendor-Dpio9q2e.js",
|
|
7
|
+
"_vendor-arizeai-DDzwX9A6.js",
|
|
8
|
+
"_pages-CU_QMYRP.js",
|
|
9
9
|
"_vendor-three-DwGkEfCM.js",
|
|
10
|
-
"_vendor-codemirror-
|
|
10
|
+
"_vendor-codemirror-xRvQKK1G.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
|
-
"_pages-
|
|
14
|
-
"file": "assets/pages-
|
|
13
|
+
"_pages-CU_QMYRP.js": {
|
|
14
|
+
"file": "assets/pages-CU_QMYRP.js",
|
|
15
15
|
"name": "pages",
|
|
16
16
|
"imports": [
|
|
17
|
-
"_vendor-
|
|
18
|
-
"_components-
|
|
19
|
-
"_vendor-arizeai-
|
|
20
|
-
"_vendor-recharts-
|
|
21
|
-
"_vendor-codemirror-
|
|
17
|
+
"_vendor-Dpio9q2e.js",
|
|
18
|
+
"_components-Ddr-5VpM.js",
|
|
19
|
+
"_vendor-arizeai-DDzwX9A6.js",
|
|
20
|
+
"_vendor-recharts-DoxlB_Wo.js",
|
|
21
|
+
"_vendor-codemirror-xRvQKK1G.js"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
24
|
"_vendor-!~{003}~.js": {
|
|
25
25
|
"file": "assets/vendor-DxkFTwjz.css",
|
|
26
26
|
"src": "_vendor-!~{003}~.js"
|
|
27
27
|
},
|
|
28
|
-
"_vendor-
|
|
29
|
-
"file": "assets/vendor-
|
|
28
|
+
"_vendor-Dpio9q2e.js": {
|
|
29
|
+
"file": "assets/vendor-Dpio9q2e.js",
|
|
30
30
|
"name": "vendor",
|
|
31
31
|
"imports": [
|
|
32
32
|
"_vendor-three-DwGkEfCM.js"
|
|
@@ -35,25 +35,25 @@
|
|
|
35
35
|
"assets/vendor-DxkFTwjz.css"
|
|
36
36
|
]
|
|
37
37
|
},
|
|
38
|
-
"_vendor-arizeai-
|
|
39
|
-
"file": "assets/vendor-arizeai-
|
|
38
|
+
"_vendor-arizeai-DDzwX9A6.js": {
|
|
39
|
+
"file": "assets/vendor-arizeai-DDzwX9A6.js",
|
|
40
40
|
"name": "vendor-arizeai",
|
|
41
41
|
"imports": [
|
|
42
|
-
"_vendor-
|
|
42
|
+
"_vendor-Dpio9q2e.js"
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
|
-
"_vendor-codemirror-
|
|
46
|
-
"file": "assets/vendor-codemirror-
|
|
45
|
+
"_vendor-codemirror-xRvQKK1G.js": {
|
|
46
|
+
"file": "assets/vendor-codemirror-xRvQKK1G.js",
|
|
47
47
|
"name": "vendor-codemirror",
|
|
48
48
|
"imports": [
|
|
49
|
-
"_vendor-
|
|
49
|
+
"_vendor-Dpio9q2e.js"
|
|
50
50
|
]
|
|
51
51
|
},
|
|
52
|
-
"_vendor-recharts-
|
|
53
|
-
"file": "assets/vendor-recharts-
|
|
52
|
+
"_vendor-recharts-DoxlB_Wo.js": {
|
|
53
|
+
"file": "assets/vendor-recharts-DoxlB_Wo.js",
|
|
54
54
|
"name": "vendor-recharts",
|
|
55
55
|
"imports": [
|
|
56
|
-
"_vendor-
|
|
56
|
+
"_vendor-Dpio9q2e.js"
|
|
57
57
|
]
|
|
58
58
|
},
|
|
59
59
|
"_vendor-three-DwGkEfCM.js": {
|
|
@@ -61,18 +61,18 @@
|
|
|
61
61
|
"name": "vendor-three"
|
|
62
62
|
},
|
|
63
63
|
"index.tsx": {
|
|
64
|
-
"file": "assets/index-
|
|
64
|
+
"file": "assets/index-BvNNAF8n.js",
|
|
65
65
|
"name": "index",
|
|
66
66
|
"src": "index.tsx",
|
|
67
67
|
"isEntry": true,
|
|
68
68
|
"imports": [
|
|
69
|
-
"_vendor-
|
|
70
|
-
"_vendor-arizeai-
|
|
71
|
-
"_pages-
|
|
72
|
-
"_components-
|
|
69
|
+
"_vendor-Dpio9q2e.js",
|
|
70
|
+
"_vendor-arizeai-DDzwX9A6.js",
|
|
71
|
+
"_pages-CU_QMYRP.js",
|
|
72
|
+
"_components-Ddr-5VpM.js",
|
|
73
73
|
"_vendor-three-DwGkEfCM.js",
|
|
74
|
-
"_vendor-recharts-
|
|
75
|
-
"_vendor-codemirror-
|
|
74
|
+
"_vendor-recharts-DoxlB_Wo.js",
|
|
75
|
+
"_vendor-codemirror-xRvQKK1G.js"
|
|
76
76
|
]
|
|
77
77
|
}
|
|
78
78
|
}
|