arize-phoenix 4.24.0__py3-none-any.whl → 4.25.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.

Files changed (44) hide show
  1. {arize_phoenix-4.24.0.dist-info → arize_phoenix-4.25.0.dist-info}/METADATA +10 -6
  2. {arize_phoenix-4.24.0.dist-info → arize_phoenix-4.25.0.dist-info}/RECORD +44 -41
  3. phoenix/auth/__init__.py +0 -0
  4. phoenix/auth/utils.py +15 -0
  5. phoenix/db/engines.py +15 -2
  6. phoenix/db/insertion/dataset.py +1 -0
  7. phoenix/db/migrate.py +21 -10
  8. phoenix/db/migrations/future_versions/cd164e83824f_users_and_tokens.py +7 -6
  9. phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +4 -12
  10. phoenix/db/models.py +1 -1
  11. phoenix/inferences/fixtures.py +1 -0
  12. phoenix/inferences/inferences.py +1 -0
  13. phoenix/metrics/__init__.py +1 -0
  14. phoenix/server/api/context.py +14 -0
  15. phoenix/server/api/mutations/__init__.py +2 -0
  16. phoenix/server/api/mutations/api_key_mutations.py +119 -0
  17. phoenix/server/api/mutations/auth.py +7 -0
  18. phoenix/server/api/queries.py +7 -6
  19. phoenix/server/api/routers/v1/datasets.py +1 -0
  20. phoenix/server/api/routers/v1/spans.py +1 -1
  21. phoenix/server/api/types/UserRole.py +1 -1
  22. phoenix/server/app.py +36 -7
  23. phoenix/server/main.py +24 -19
  24. phoenix/server/static/.vite/manifest.json +31 -31
  25. phoenix/server/static/assets/{components-DzA9gIHT.js → components-1Ahruijo.js} +4 -4
  26. phoenix/server/static/assets/{index-BuTlV4Gk.js → index-BEE_RWJx.js} +2 -2
  27. phoenix/server/static/assets/{pages-DzkUGFGV.js → pages-CFS6mPnW.js} +263 -220
  28. phoenix/server/static/assets/{vendor-CIqy43_9.js → vendor-aSQri0vz.js} +58 -58
  29. phoenix/server/static/assets/{vendor-arizeai-B1YgcWL8.js → vendor-arizeai-CsdcB1NH.js} +1 -1
  30. phoenix/server/static/assets/{vendor-codemirror-_bcwCA1C.js → vendor-codemirror-CYHkhs7D.js} +1 -1
  31. phoenix/server/static/assets/{vendor-recharts-C3pM_Wlg.js → vendor-recharts-B0sannek.js} +1 -1
  32. phoenix/server/types.py +12 -4
  33. phoenix/services.py +1 -0
  34. phoenix/session/client.py +1 -1
  35. phoenix/session/evaluation.py +1 -0
  36. phoenix/session/session.py +2 -1
  37. phoenix/trace/fixtures.py +37 -0
  38. phoenix/trace/langchain/instrumentor.py +1 -1
  39. phoenix/trace/llama_index/callback.py +1 -0
  40. phoenix/trace/openai/instrumentor.py +1 -0
  41. phoenix/version.py +1 -1
  42. {arize_phoenix-4.24.0.dist-info → arize_phoenix-4.25.0.dist-info}/WHEEL +0 -0
  43. {arize_phoenix-4.24.0.dist-info → arize_phoenix-4.25.0.dist-info}/licenses/IP_NOTICE +0 -0
  44. {arize_phoenix-4.24.0.dist-info → arize_phoenix-4.25.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.24.0
3
+ Version: 4.25.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
@@ -42,9 +42,11 @@ Requires-Dist: protobuf<6.0,>=3.20
42
42
  Requires-Dist: psutil
43
43
  Requires-Dist: pyarrow
44
44
  Requires-Dist: pydantic!=2.0.*,<3,>=1.0
45
+ Requires-Dist: pyjwt
45
46
  Requires-Dist: python-multipart
46
47
  Requires-Dist: scikit-learn
47
- Requires-Dist: scipy
48
+ Requires-Dist: scipy!=1.14.1; platform_system == 'Darwin'
49
+ Requires-Dist: scipy; platform_system != 'Darwin'
48
50
  Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
49
51
  Requires-Dist: sqlean-py>=3.45.1
50
52
  Requires-Dist: starlette
@@ -85,14 +87,16 @@ Requires-Dist: nbqa; extra == 'dev'
85
87
  Requires-Dist: pandas-stubs==2.0.3.230814; (python_version < '3.9') and extra == 'dev'
86
88
  Requires-Dist: pandas-stubs==2.2.2.240603; (python_version >= '3.9') and extra == 'dev'
87
89
  Requires-Dist: pandas>=1.0; extra == 'dev'
90
+ Requires-Dist: portpicker; extra == 'dev'
88
91
  Requires-Dist: pre-commit; extra == 'dev'
89
92
  Requires-Dist: prometheus-client; extra == 'dev'
90
93
  Requires-Dist: psycopg[binary]; extra == 'dev'
91
94
  Requires-Dist: pytest-asyncio; extra == 'dev'
92
95
  Requires-Dist: pytest-cov; extra == 'dev'
93
96
  Requires-Dist: pytest-postgresql; extra == 'dev'
94
- Requires-Dist: pytest==8.3.1; extra == 'dev'
95
- Requires-Dist: ruff==0.5.4; extra == 'dev'
97
+ Requires-Dist: pytest-xdist; extra == 'dev'
98
+ Requires-Dist: pytest==8.3.2; extra == 'dev'
99
+ Requires-Dist: ruff==0.6.1; extra == 'dev'
96
100
  Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.236.0; extra == 'dev'
97
101
  Requires-Dist: tabulate; extra == 'dev'
98
102
  Requires-Dist: types-tabulate; extra == 'dev'
@@ -107,6 +111,7 @@ Requires-Dist: llama-index-readers-file==0.1.25; extra == 'llama-index'
107
111
  Requires-Dist: llama-index==0.10.51; extra == 'llama-index'
108
112
  Provides-Extra: pg
109
113
  Requires-Dist: asyncpg; extra == 'pg'
114
+ Provides-Extra: test
110
115
  Description-Content-Type: text/markdown
111
116
 
112
117
  <p align="center">
@@ -144,9 +149,8 @@ Phoenix is an open-source AI observability platform designed for experimentation
144
149
  - **_Evaluation_** - Leverage LLMs to benchmark your application's performance using response and retrieval evals.
145
150
  - **_Datasets_** - Create versioned datasets of examples for experimentation, evaluation, and fine-tuning.
146
151
  - **_Experiments_** - Track and evaluate changes to prompts, LLMs, and retrieval.
147
- - **_Inference Analysis_** - Visualize inferences and embeddings using dimensionality reduction and clustering to identify drift and performance degradation.
148
152
 
149
- Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙LlamaIndex, 🦜⛓LangChain, 🧩DSPy) and LLM providers (OpenAI, Bedrock, and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
153
+ Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙LlamaIndex, 🦜⛓LangChain, Haystack, 🧩DSPy) and LLM providers (OpenAI, Bedrock, and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
150
154
 
151
155
  Phoenix runs practically anywhere, including your Jupyter notebook, local machine, containerized deployment, or in the cloud.
152
156
 
@@ -3,9 +3,11 @@ phoenix/config.py,sha256=wYA_8GSSz5rnpfIWDjeBL9ehKuTy9jqXaMZnxUqRYEU,10131
3
3
  phoenix/datetime_utils.py,sha256=yDKjwX2Vtqw9h5F_ProtP-TsXidM43uIvmJ_pOzYc9A,3405
4
4
  phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
5
5
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
- phoenix/services.py,sha256=aTxhcOA1pZHB6U-B3TEcp6fqDF5oT0xCUvEUNMZVTUQ,5175
6
+ phoenix/services.py,sha256=OyML4t2XGnlqF0JXA9_uccL8HslTABxep9Ci7MViKEU,5216
7
7
  phoenix/settings.py,sha256=cO-qgis_S27nHirTobYI9hHPfZH18R--WMmxNdsVUwc,273
8
- phoenix/version.py,sha256=l7f0EI2kXBLXXp82SILFQvXoX83QSluu_cmoTReAP9g,23
8
+ phoenix/version.py,sha256=gMIFKEThnzM4tu5IZY3JHWVjHbXMgpnlK4Y7S0AWlGs,23
9
+ phoenix/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ phoenix/auth/utils.py,sha256=g-97oiJR219P6JvDUU5likHN4CdWtWo7bDJRmfVb0qk,450
9
11
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
12
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
11
13
  phoenix/core/model.py,sha256=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
@@ -15,13 +17,13 @@ phoenix/db/README.md,sha256=IvKaZyf9ECbGBYYePaRhBveKZwDbxAc-c7BMxJYZh6Q,595
15
17
  phoenix/db/__init__.py,sha256=pDjEFXukHmJBM-1D8RjmXkvLsz85YWNxMQczt81ec3A,118
16
18
  phoenix/db/alembic.ini,sha256=p8DjVqGUs_tTx8oU56JP7qj-rMUebNFizItUSv_hPhs,3763
17
19
  phoenix/db/bulk_inserter.py,sha256=qgg8pt5k4VnHKOE0-KoReXVAfXRhLt-sMZihI-b4X9I,12761
18
- phoenix/db/engines.py,sha256=R3btYTSOSd6BwRA59EmhhojL0HCQ7NnzFIXQrPYS0iU,4812
20
+ phoenix/db/engines.py,sha256=QDdRE6AM7JHWotAGCCljbaM_tz2hHB3-TSr_F4KUe-Q,5292
19
21
  phoenix/db/helpers.py,sha256=2zSc4n5IJfu-CaOFoBfqTB35M1nTFcAc8tqLsNtF2Jw,3488
20
- phoenix/db/migrate.py,sha256=MuhtNWnR24riROvarvKfbRb4_D5xuQi6P760vBUKl1E,2270
21
- phoenix/db/models.py,sha256=96XA9m3vV-HpQDggHqGWPNvAOEMANediIbvvqAUaY7U,23686
22
+ phoenix/db/migrate.py,sha256=NNcci4LHw0wFR7U6quWrA-sw_A4h2lAA1_LePMLkb4w,2629
23
+ phoenix/db/models.py,sha256=lYWJYtD2asQwKU1B8JKyteWpHVYjhr1j0tmZdf9CQ5Y,23686
22
24
  phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
25
  phoenix/db/insertion/constants.py,sha256=8wifm7X-1XvroZ__R2Gc96NsgLhTDn0zXl4lehlXtcA,70
24
- phoenix/db/insertion/dataset.py,sha256=_vxy5e6W5jEuvO2fMKbbNCn9JvHkwI4LRKk_10eKFVg,7171
26
+ phoenix/db/insertion/dataset.py,sha256=vBIroaSIWz5ZXE0Hul8osbebjS40gDCbsSP-YnazEwk,7212
25
27
  phoenix/db/insertion/document_annotation.py,sha256=qp8E63LzlthAScQg6opqln5Qg1d7UdtP3rkYL4riTgU,5983
26
28
  phoenix/db/insertion/evaluation.py,sha256=SoI85N3MYUSeNgjKa5WzFw14OfNjNTjExv-2m3sxaR8,6371
27
29
  phoenix/db/insertion/helpers.py,sha256=z_Wnckhdf-F7xadWgaAV5ScXnLft8EtaYJCuIkma2Vw,3486
@@ -33,10 +35,10 @@ phoenix/db/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
33
35
  phoenix/db/migrations/env.py,sha256=QbzB5zrRs6XQQmrYeUpuzeilcMlM-MsbaAgHHYcIHTI,3626
34
36
  phoenix/db/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
35
37
  phoenix/db/migrations/future_versions/README.md,sha256=3QtDx40SAD-IITjbdlKR2N_CBxT5y37C1OQs05EDt7o,184
36
- phoenix/db/migrations/future_versions/cd164e83824f_users_and_tokens.py,sha256=6iSewwJCLbGWG1qojJHDiwM-6GIddgsLlGosVdSo6s8,8794
38
+ phoenix/db/migrations/future_versions/cd164e83824f_users_and_tokens.py,sha256=J2HD50V8GPuj6UVFOvUCuXtiTOLPU-MxrhRlMcpdBb0,8795
37
39
  phoenix/db/migrations/versions/.gitignore,sha256=chLdMrfkICZvLY7lCEcuqF32sVp61Jml4PodFryEU94,33
38
40
  phoenix/db/migrations/versions/10460e46d750_datasets.py,sha256=eZAyz720DmpOd7RnuxDN2dVNXVuMrdlCA7eAOxyMtfs,8695
39
- phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py,sha256=x6oKFwn7Zmite4G0trDQPpMCn0I7jejuBcN3-ivEuDg,3938
41
+ phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py,sha256=bV7urfCPkrXhkyg8oaUfLYN093UoRecLQXPkXJ8SIOs,3666
40
42
  phoenix/db/migrations/versions/cf03bd6bae1d_init.py,sha256=09cpofqje8zi4eQFfUn-i21x7VcsUYOfLKKUlrtKrGc,8662
41
43
  phoenix/experiments/__init__.py,sha256=6JGwgUd7xCbGpuHqYZlsmErmYvVgv7N_j43bn3dUqsk,123
42
44
  phoenix/experiments/functions.py,sha256=B60_JT0jmLFQbkweZc2Px1q1vzE3Q_w2EI5jRgT19Rk,32589
@@ -50,12 +52,12 @@ phoenix/experiments/evaluators/llm_evaluators.py,sha256=zyGhxXBDNi1qoj_8I95PRSwj
50
52
  phoenix/experiments/evaluators/utils.py,sha256=XYqB0bOljyR0GewmR_mm9Ndl_q95EkjjDqfXd7YVqTk,9303
51
53
  phoenix/inferences/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
54
  phoenix/inferences/errors.py,sha256=cGp9vxnw4SewFoWBV3ZGMkhE0Kh73lPIv3Ppz_H_RoA,8261
53
- phoenix/inferences/fixtures.py,sha256=FC2eRL4dpobKQHYOilFtDexUWFkMZ_w6jun_4WkbMk0,20792
54
- phoenix/inferences/inferences.py,sha256=aH2uHRJR4_W7CVy3EMEioaEBM8cTRYBUyVuDDVjwVXw,31106
55
+ phoenix/inferences/fixtures.py,sha256=r5mN8I58rirO2YqHr_88G2aRC0ADYLSKozgxEG89MTM,20833
56
+ phoenix/inferences/inferences.py,sha256=r-ByeW_AU6cu199iJMn_Td3XywqtRfrLS7cDuHaayUA,31147
55
57
  phoenix/inferences/schema.py,sha256=UYej9IJ6pFeNW3fq721kJy16ONso_xVDm78Q68G4hl4,6643
56
58
  phoenix/inferences/validation.py,sha256=fdmbsjUBwtacRiVFdh9aem-QrgPfq_OlEmPdascWluc,8297
57
59
  phoenix/metrics/README.md,sha256=5gekqTU-5gGdMwvcfNp2Wlu8p1ul9kGY_jq0XXQusoI,1964
58
- phoenix/metrics/__init__.py,sha256=W8lVORvjBo66pFgUmU9P8Fi8i4yI75wOPkhU42sfeQU,2417
60
+ phoenix/metrics/__init__.py,sha256=OZ7Hc3iGsnGE6bgoDCy0BVEozcYTbE2Qu4VXpdu8KYk,2458
59
61
  phoenix/metrics/binning.py,sha256=jDd7YcyEhptCp3zWcH6tfyq87vJ3c8L50ocSuxgPAoQ,12739
60
62
  phoenix/metrics/metrics.py,sha256=7SfkDmSnpzGATtBXlYHb42r-2BfV8ELMcMgjdw3c8yA,7907
61
63
  phoenix/metrics/mixins.py,sha256=moZ5hENIKzUQt2IRhWOd5EFXnoqQkVrpqEqMH7KQzyA,7440
@@ -68,19 +70,19 @@ phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYG
68
70
  phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
69
71
  phoenix/pointcloud/umap_parameters.py,sha256=3UQSjrysVOvq2V4KNpTMqNqNiK0BsTZnPBHWZ4fyJtQ,1708
70
72
  phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- phoenix/server/app.py,sha256=A0IIC7ONjBlRWqfAjoCqfoVS0xcnPfWk3gmxphgAjcM,19674
73
+ phoenix/server/app.py,sha256=Jy_QX0YpX6wSHe9oz45gU3VCaQ18dyyWsOxM-xcOul4,21149
72
74
  phoenix/server/dml_event.py,sha256=MpjCFqljxvgb9OB5Cez9vJesb3oHb3XxXictynBfcis,2851
73
75
  phoenix/server/dml_event_handler.py,sha256=6p-PucctivelVHfO-_9zNxWZYPr_eGjDF3bKjLtc5co,8251
74
76
  phoenix/server/grpc_server.py,sha256=jllxDNkpLQxDkvej4RhTokobowbvydF-SU8gSw1MTCc,3378
75
- phoenix/server/main.py,sha256=xxG650qi2bIX6HCcfSiLd1QyImiBoWbsVJ55m21GyNg,11471
77
+ phoenix/server/main.py,sha256=rcXBEcSpnwFHwTZcMIu3s8Y7ABCMEZYJ0xb8wKtBfL0,11731
76
78
  phoenix/server/prometheus.py,sha256=j9DHB2fERuq_ZKmwVaqR-9wx5WcPPuU1Cm5Bhg5241Y,2996
77
79
  phoenix/server/telemetry.py,sha256=T_2OKrxNViAeaANlNspEekg_Y5uZIFWvKAnpz8Aoqvk,2762
78
80
  phoenix/server/thread_server.py,sha256=RwXQGP_QhGD7le6WB7xEygEEuwBl5Ck_Zo8xGIYGi9M,2135
79
- phoenix/server/types.py,sha256=UCCkwEzUAbRdu-hZpG7A2hdPM09onBezaXNtWX4A7og,3431
81
+ phoenix/server/types.py,sha256=S2dReLNboR2nzjRK5j3MUyUDqu6AQFD7KRwJkeKj1q4,3609
80
82
  phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
- phoenix/server/api/context.py,sha256=2-kJpoix-OISxyAhoI5FFEnQMt9ad-3HQ3VOFCjdbxU,2799
83
+ phoenix/server/api/context.py,sha256=N_kqhQIlRyPS6JpN-fgCZ2U4_ZbhaknH-23g5JoRU8g,3282
82
84
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
83
- phoenix/server/api/queries.py,sha256=cO47wUByLDTjrt4N28kVkQbxbJXusZ8TTCkXiIcEuaU,23804
85
+ phoenix/server/api/queries.py,sha256=GXQzz1KmRqZCOENemdgoqBlTVA_4V2AZE-g0hBcO0Qk,23839
84
86
  phoenix/server/api/schema.py,sha256=BcxdqO5CSGqpKd-AAJHMjFlzaK9oJA8GJuxmMfcdjn4,434
85
87
  phoenix/server/api/utils.py,sha256=Kl47G-1A7QKTDrc75BU2QK6HupsG6MWuXxy351FOfKQ,858
86
88
  phoenix/server/api/dataloaders/__init__.py,sha256=TrOGnU_SD_vEIxOE_dm8HrD5C2ScLFQ4xQ7f8r-E76s,3064
@@ -137,8 +139,9 @@ phoenix/server/api/input_types/SpanSort.py,sha256=Dhvl8BIoV52yHoqntfOax_gUc15uH8
137
139
  phoenix/server/api/input_types/TimeRange.py,sha256=yzx-gxj8mDeGLft1FzU_x1MVEgIG5Pt6-f8PUVDgipQ,522
138
140
  phoenix/server/api/input_types/TraceAnnotationSort.py,sha256=BzwiUnMh2VsgQYnhDlbJ6ljHugqIS4YDUlYzvq_tl3o,365
139
141
  phoenix/server/api/input_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
- phoenix/server/api/mutations/__init__.py,sha256=UKUAhD5NY-ZI7XONnRRkaHoFuuU3idmE4fk6Sjgy18M,776
141
- phoenix/server/api/mutations/auth.py,sha256=vPRFoj7J6PV6QeODewG4K0PhoOebS5AfMRpbi_wuhyQ,311
142
+ phoenix/server/api/mutations/__init__.py,sha256=XFlHUZKD6oJWfnXVXOoP1HYeC7Jdw1TntmAUnOQWn8M,880
143
+ phoenix/server/api/mutations/api_key_mutations.py,sha256=cv6AT6UAL55lTC_UqMdcN-1TjWAgqqZi__S9Tw12t6I,3688
144
+ phoenix/server/api/mutations/auth.py,sha256=8o4tTfGCPkpUauuB9ijPH84Od77UX_UrQWfmUsnujI4,524
142
145
  phoenix/server/api/mutations/dataset_mutations.py,sha256=0feBUW_07FEIx6uzepjxfRVhk5lAck0AkrqS1GVdoF4,27041
143
146
  phoenix/server/api/mutations/experiment_mutations.py,sha256=OXtLYdLA33RGy1MFctfv6ug2sODcDElhJph_J9vkIjk,3157
144
147
  phoenix/server/api/mutations/export_events_mutations.py,sha256=t_wYBxaqvBJYRoHslh3Bmoxmwlzoy0u8SsBKWIKN5hE,4028
@@ -151,13 +154,13 @@ phoenix/server/api/openapi/schema.py,sha256=oVZoflWMfzOrLKMIrjr3iLnJ13rmN-t_DOe9
151
154
  phoenix/server/api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
155
  phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
153
156
  phoenix/server/api/routers/v1/__init__.py,sha256=nb49zcOdAi3DSGuC9gUubN9Yri-o7-WFdlGak4jGuFw,1462
154
- phoenix/server/api/routers/v1/datasets.py,sha256=pyLtVEGnjwxh1wJySBOUFrsjtawatfpaF8F3WijK8qU,37049
157
+ phoenix/server/api/routers/v1/datasets.py,sha256=l3Hlc9AVyvX5GdT9iOXBsV-i4c_vtnCaXeSAWdNzcw8,37090
155
158
  phoenix/server/api/routers/v1/evaluations.py,sha256=FSfz9MTi8s65F07abDXlb9-y97fDZSYbqsCXpimwO7g,12628
156
159
  phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=RTQnjupjmh07xowjq77ajbuAZhzIEfYxA4ZtECvGwOU,4844
157
160
  phoenix/server/api/routers/v1/experiment_runs.py,sha256=0G7GgGcZv9dzK47tsPp-p4k5O7W4F_aNRrsNuJN7mho,6393
158
161
  phoenix/server/api/routers/v1/experiments.py,sha256=GeT3Rya4bdaCr6sCf2Vx6fQ_gfMX5XyFHmODCSJiCfU,9951
159
162
  phoenix/server/api/routers/v1/pydantic_compat.py,sha256=FeK8oe2brqu-djsoqRxiKL4tw5cHmi89OHVfCFxYsAo,2890
160
- phoenix/server/api/routers/v1/spans.py,sha256=Hd63VHQUqSy0VHsYQ5DPLf5WwKALMXZOIh_ig_5MStc,8780
163
+ phoenix/server/api/routers/v1/spans.py,sha256=MAkMLrONFtItQxkHJde_Wpvz0jsgydegxVZOkZkRUsU,8781
161
164
  phoenix/server/api/routers/v1/traces.py,sha256=HJDmYKMATL40dZEJro6uQ3imbCZBzk3nUun9d21jcDs,7799
162
165
  phoenix/server/api/routers/v1/utils.py,sha256=xvl2v-BKUkqmFVMmgmmWGFKuRBTrUdoiAeT3mCYEE68,3086
163
166
  phoenix/server/api/types/Annotation.py,sha256=7Ym7iuVcbwHlw2yIRylz4nATAF_Cm-Z17qcjiooj1cc,751
@@ -215,7 +218,7 @@ phoenix/server/api/types/TraceAnnotation.py,sha256=OW6A2zr1gomOuG0XQe55dk15XXX2D
215
218
  phoenix/server/api/types/UMAPPoints.py,sha256=5sOuruzM8saXa8C2XiyUfk2XPrkVGmhqKpclMYRw1dk,1656
216
219
  phoenix/server/api/types/User.py,sha256=j04JLq51GBqjcAuZfErUn05bB3nSpy-DlNL2jm4AaHA,300
217
220
  phoenix/server/api/types/UserApiKey.py,sha256=ZHfCHHxPUE5CSKiQuCqzlY7GkSZ5OzvcORoBMRPA3gg,227
218
- phoenix/server/api/types/UserRole.py,sha256=VydiFaNIjcuYtvrkBykhWc2nXvHWWhAUsZ9D1Tyqdng,140
221
+ phoenix/server/api/types/UserRole.py,sha256=I6QuYMZRuJT0kKs6KQQYroCZ9D60MQWdzNqdlvOYmRk,140
219
222
  phoenix/server/api/types/ValidationResult.py,sha256=pHwdYk4J7SJ5xhlWWHg_6qWkfk4rjOx-bSkGHvkDE3Q,142
220
223
  phoenix/server/api/types/VectorDriftMetricEnum.py,sha256=etiJM5ZjQuD-oE7sY-FbdIKY050jk3IU49IMwmfJbEc,188
221
224
  phoenix/server/api/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -232,29 +235,29 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
232
235
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
233
236
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
234
237
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
235
- phoenix/server/static/.vite/manifest.json,sha256=Sc2AOYCyZmm4BdNQ7itmmI9AFoBxJzfMoZC8YoWh1gA,1929
236
- phoenix/server/static/assets/components-DzA9gIHT.js,sha256=miEpsrzpn_BM4W1HFe2dvNJJILaO8sq677NhjhiL8w4,187160
237
- phoenix/server/static/assets/index-BuTlV4Gk.js,sha256=JsAPpelKgf1a9JtrnyKLgJn4w3vUzYLCk5bsCXnCnkM,7466
238
- phoenix/server/static/assets/pages-DzkUGFGV.js,sha256=qX2Q1wyfONVCfbx7uPd2W33MIZ4B561SIl0TO2LDK1Y,457253
239
- phoenix/server/static/assets/vendor-CIqy43_9.js,sha256=YclKUblIZ8JB6hhl36BtG_7FEsrNYbgnsW0d0w6zIxk,1355423
238
+ phoenix/server/static/.vite/manifest.json,sha256=5TDpyzP0p7LFbVpIP1n6hAq2Y9BIMRY07AZTk7p3_pA,1929
239
+ phoenix/server/static/assets/components-1Ahruijo.js,sha256=wZdgukvLzeGCBdNCLuU-yOra8gsjFIuC9hSEwa7LuDw,187182
240
+ phoenix/server/static/assets/index-BEE_RWJx.js,sha256=WrJXGQvMa2pSjnH_xjCwyRmDfm9MVD6FXq0YytraYEI,7461
241
+ phoenix/server/static/assets/pages-CFS6mPnW.js,sha256=OLH9XUE7sS_MRSpD7x-CW4PJt981P-C2biAvQ0dO88g,466231
240
242
  phoenix/server/static/assets/vendor-DxkFTwjz.css,sha256=nZrkr0u6NNElFGvpWHk9GTHeGoibCXCli1bE7mXZGZg,1816
241
- phoenix/server/static/assets/vendor-arizeai-B1YgcWL8.js,sha256=b-Q3bHiEkWo29daqYevZItyECmgFu0LMjYgpbDK3mSc,304008
242
- phoenix/server/static/assets/vendor-codemirror-_bcwCA1C.js,sha256=oqAOjM0IviW-Si9fscZsSTR3_aj2vdp8H6acoyIFzek,503031
243
- phoenix/server/static/assets/vendor-recharts-C3pM_Wlg.js,sha256=gnMIx0IktJjLzrgDehKdRebp3EkFAGli_067pIMVXFY,282859
243
+ phoenix/server/static/assets/vendor-aSQri0vz.js,sha256=x_07SENutKMhtJ9HgFqkQHvwsDTfPkMmzQznY3HY7Zo,1359197
244
+ phoenix/server/static/assets/vendor-arizeai-CsdcB1NH.js,sha256=VEn7hFJXcHV_DODmeDi9pEpF_D2NQ1bZYewbPe3BhIw,304008
245
+ phoenix/server/static/assets/vendor-codemirror-CYHkhs7D.js,sha256=FmRfBdG2nCiQBDRc5bleOXwtUlepZjabWDnYhRq5rsc,503031
246
+ phoenix/server/static/assets/vendor-recharts-B0sannek.js,sha256=Fi6Z_dwtI67mHHAdHISUHWzZQYsOwV1NGtomvOLv9xA,282859
244
247
  phoenix/server/static/assets/vendor-three-DwGkEfCM.js,sha256=0D12ZgKzfKCTSdSTKJBFR2RZO_xxeMXrqDp0AszZqHY,620972
245
248
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
246
249
  phoenix/server/templates/index.html,sha256=dAm0IClgJUdT5AOmjZvtgMg8F_xGrRGv95SAkUyx_kg,4325
247
250
  phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
248
- phoenix/session/client.py,sha256=C-NpmDkcyGZHR0vv5gWtteUi01cIorjWnqie9WuZb9s,32663
251
+ phoenix/session/client.py,sha256=GzeSHbNQOh5dyzHV90t_cHJpn5VL0vkNmSnaMq-2ug4,32703
249
252
  phoenix/session/data_extractor.py,sha256=gkEM3WWZAlWGMfRgQopAQlid4cSi6GNco-sdrGir0qc,2788
250
- phoenix/session/evaluation.py,sha256=aKeV8UVOyq3b7CYOwt3cWuLz0xzvMjX7vlEPILJ_fcs,5311
251
- phoenix/session/session.py,sha256=LOdcO7_XMArUMnyRlikLMZq41jgZ0Vl_BxDEpYxF4UU,26953
253
+ phoenix/session/evaluation.py,sha256=3a33ilo-WU0F_Ze26lkCMMwni0GGceSXRRBLvP3CI1o,5352
254
+ phoenix/session/session.py,sha256=3DSpXj_mlRAKnb9aNUkDjph19SLHx32IJSKYcR3r7cw,26994
252
255
  phoenix/trace/__init__.py,sha256=ujk_uYjM8gmm-YqnyXxF-kekfwid0bcaPMTtNNcaw6U,407
253
256
  phoenix/trace/attributes.py,sha256=B_OrzVaxZwFkrAFXZyicYoIti1UdUysURsvUS2GyW1U,12488
254
257
  phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
255
258
  phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
256
259
  phoenix/trace/exporter.py,sha256=eAYemdvDCHMugDJiaR29BFFMTQBdf3oerdkz34Cl3hE,4736
257
- phoenix/trace/fixtures.py,sha256=LABY-H6BdDA-fS9dZ13uTovXCPTdfWcvU8HsJ_qPspc,14106
260
+ phoenix/trace/fixtures.py,sha256=PgawxpyxXz2596gJEj0yU27t-zcphz_ORGsxeAMvjKY,15345
258
261
  phoenix/trace/otel.py,sha256=WA720jvRadiZBAKjsYoPyXzypHwbyEK2OZRVUwtbjB8,9976
259
262
  phoenix/trace/projects.py,sha256=2BwlNjFE-uwpqYtCu5YyBiYZk9wRPpM13vh3-Cv7GkA,2157
260
263
  phoenix/trace/schemas.py,sha256=HpWSyzec0yDHEQXEDuwyLbhpvKrqkGps8BJqGiIFj8Y,5978
@@ -269,11 +272,11 @@ phoenix/trace/dsl/filter.py,sha256=9NwATCUOgJ4Pms8XsEcinROUuxZ9UW-ISV09o65Ms70,3
269
272
  phoenix/trace/dsl/helpers.py,sha256=ULAhqWULPqYWCSNX7y50DVKIqfySx86nqb6hDvZPnVk,3896
270
273
  phoenix/trace/dsl/query.py,sha256=W0t-tiXh2WIVb96lzFAGQOQ-U46uKux78d4KL3rW-PE,30316
271
274
  phoenix/trace/langchain/__init__.py,sha256=F37GfD1pd5Kuw7R7iRUM1zXXpO8xEcycNZh5dwqBXNk,109
272
- phoenix/trace/langchain/instrumentor.py,sha256=isW3KRRP55t3JeaipAJ_aS7N_3HtwScPCO67ymSLr0Y,1372
275
+ phoenix/trace/langchain/instrumentor.py,sha256=zdh9uZfG7HWna6Wug_agS7MxSbUlfV-nhf3jWFZm61U,1412
273
276
  phoenix/trace/llama_index/__init__.py,sha256=4fpR5702Qh2t5TaXIx584EkA-BveCPftXPOKvI0Oi3I,105
274
- phoenix/trace/llama_index/callback.py,sha256=ROGgpbkXDc54Yr2S28WqoZoH4rJrUDsPTdEsP0F7AB4,4451
277
+ phoenix/trace/llama_index/callback.py,sha256=0EIyHorb0QjTn9kKW_dzrUfvl5d6re-tx_GesIAuDGY,4492
275
278
  phoenix/trace/openai/__init__.py,sha256=J3G0uqCxGdksUpaQVHds_Egv2drvh8UEqoLjiQAOveg,79
276
- phoenix/trace/openai/instrumentor.py,sha256=sb3434Npe86VHsT_jyDHlfpXWZYER9H1k_IQ5-CFTvI,1270
279
+ phoenix/trace/openai/instrumentor.py,sha256=b_QT5KFgDdgfUV9X4MSwnqFgGxAo-jxduJk3KtWBzKo,1311
277
280
  phoenix/trace/v1/__init__.py,sha256=-IbAD0ruESMjvQLvGAg9CTfjBUATFDx1OXseDPis6-0,88
278
281
  phoenix/trace/v1/evaluation_pb2.py,sha256=8sXvv2BW_vqD30MOMbmkeE2zpmm7ncik21kl3e-HzeQ,2254
279
282
  phoenix/trace/v1/evaluation_pb2.pyi,sha256=cCbbx06gwQmaH14s3J1X25TtaARh-k1abbxQdQCXGm8,4500
@@ -286,8 +289,8 @@ phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,
286
289
  phoenix/utilities/project.py,sha256=8IJuMM4yUMoooPi37sictGj8Etu9rGmq6RFtc9848cQ,436
287
290
  phoenix/utilities/re.py,sha256=PDve_OLjRTM8yQQJHC8-n3HdIONi7aNils3ZKRZ5uBM,2045
288
291
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
289
- arize_phoenix-4.24.0.dist-info/METADATA,sha256=EPfELiqfJFn2mwDGfD5En4FTu66BEa_cmlyblNqkvBI,11902
290
- arize_phoenix-4.24.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
291
- arize_phoenix-4.24.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
292
- arize_phoenix-4.24.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
293
- arize_phoenix-4.24.0.dist-info/RECORD,,
292
+ arize_phoenix-4.25.0.dist-info/METADATA,sha256=zbUCVE7dfjz9AjNV6ZOauoujdQmaAZwXsn02rUz4UhM,11967
293
+ arize_phoenix-4.25.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
294
+ arize_phoenix-4.25.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
295
+ arize_phoenix-4.25.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
296
+ arize_phoenix-4.25.0.dist-info/RECORD,,
File without changes
phoenix/auth/utils.py ADDED
@@ -0,0 +1,15 @@
1
+ from hashlib import pbkdf2_hmac
2
+
3
+
4
+ def compute_password_hash(password: str, salt: str) -> str:
5
+ """
6
+ Salts and hashes a password using PBKDF2, HMAC, and SHA256.
7
+ """
8
+ password_bytes = password.encode("utf-8")
9
+ salt_bytes = salt.encode("utf-8")
10
+ password_hash_bytes = pbkdf2_hmac("sha256", password_bytes, salt_bytes, NUM_ITERATIONS)
11
+ password_hash = password_hash_bytes.hex()
12
+ return password_hash
13
+
14
+
15
+ NUM_ITERATIONS = 1_000_000
phoenix/db/engines.py CHANGED
@@ -7,6 +7,7 @@ from typing import Any
7
7
 
8
8
  import aiosqlite
9
9
  import numpy as np
10
+ import sqlalchemy
10
11
  import sqlean
11
12
  from sqlalchemy import URL, StaticPool, event, make_url
12
13
  from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
@@ -15,6 +16,7 @@ from typing_extensions import assert_never
15
16
  from phoenix.db.helpers import SupportedSQLDialect
16
17
  from phoenix.db.migrate import migrate_in_thread
17
18
  from phoenix.db.models import init_models
19
+ from phoenix.settings import Settings
18
20
 
19
21
  sqlean.extensions.enable("text", "stats")
20
22
 
@@ -118,7 +120,13 @@ def aio_sqlite_engine(
118
120
  else:
119
121
  asyncio.create_task(init_models(engine))
120
122
  else:
121
- migrate_in_thread(engine.url)
123
+ sync_engine = sqlalchemy.create_engine(
124
+ url=url.set(drivername="sqlite"),
125
+ echo=Settings.log_migrations,
126
+ json_serializer=_dumps,
127
+ creator=lambda: sqlean.connect(f"file:{database}", uri=True),
128
+ )
129
+ migrate_in_thread(sync_engine)
122
130
  return engine
123
131
 
124
132
 
@@ -130,7 +138,12 @@ def aio_postgresql_engine(
130
138
  engine = create_async_engine(url=url, echo=echo, json_serializer=_dumps)
131
139
  if not migrate:
132
140
  return engine
133
- migrate_in_thread(engine.url)
141
+ sync_engine = sqlalchemy.create_engine(
142
+ url=url.set(drivername="postgresql"),
143
+ echo=Settings.log_migrations,
144
+ json_serializer=_dumps,
145
+ )
146
+ migrate_in_thread(sync_engine)
134
147
  return engine
135
148
 
136
149
 
@@ -24,6 +24,7 @@ from phoenix.db import models
24
24
  from phoenix.db.insertion.helpers import DataManipulationEvent
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
+ logger.addHandler(logging.NullHandler())
27
28
 
28
29
  DatasetId: TypeAlias = int
29
30
  DatasetVersionId: TypeAlias = int
phoenix/db/migrate.py CHANGED
@@ -1,25 +1,34 @@
1
+ import codecs
1
2
  import logging
3
+ import sys
2
4
  from pathlib import Path
3
- from queue import Empty, Queue
5
+ from queue import Empty, SimpleQueue
4
6
  from threading import Thread
5
7
  from typing import Optional
6
8
 
7
9
  from alembic import command
8
10
  from alembic.config import Config
9
- from sqlalchemy import URL
11
+ from sqlalchemy import Engine
10
12
 
11
13
  from phoenix.exceptions import PhoenixMigrationError
12
14
  from phoenix.settings import Settings
13
15
 
14
16
  logger = logging.getLogger(__name__)
17
+ logger.addHandler(logging.NullHandler())
15
18
 
16
19
 
17
20
  def printif(condition: bool, text: str) -> None:
18
- if condition:
19
- print(text)
21
+ if not condition:
22
+ return
23
+ if sys.platform.startswith("win"):
24
+ text = codecs.encode(text, "ascii", errors="ignore").decode("ascii").strip()
25
+ print(text)
20
26
 
21
27
 
22
- def migrate(url: URL, error_queue: Optional["Queue[Exception]"] = None) -> None:
28
+ def migrate(
29
+ engine: Engine,
30
+ error_queue: Optional["SimpleQueue[BaseException]"] = None,
31
+ ) -> None:
23
32
  """
24
33
  Runs migrations on the database.
25
34
  NB: Migrate only works on non-memory databases.
@@ -37,24 +46,26 @@ def migrate(url: URL, error_queue: Optional["Queue[Exception]"] = None) -> None:
37
46
  # Explicitly set the migration directory
38
47
  scripts_location = str(Path(__file__).parent.resolve() / "migrations")
39
48
  alembic_cfg.set_main_option("script_location", scripts_location)
40
- alembic_cfg.set_main_option("sqlalchemy.url", str(url).replace("%", "%%"))
49
+ url = str(engine.url).replace("%", "%%")
50
+ alembic_cfg.set_main_option("sqlalchemy.url", url)
51
+ alembic_cfg.attributes["connection"] = engine.connect()
41
52
  command.upgrade(alembic_cfg, "head")
42
53
  printif(log_migrations, "---------------------------")
43
54
  printif(log_migrations, "✅ Migrations complete.")
44
- except Exception as e:
55
+ except BaseException as e:
45
56
  if error_queue:
46
57
  error_queue.put(e)
47
58
  raise e
48
59
 
49
60
 
50
- def migrate_in_thread(url: URL) -> None:
61
+ def migrate_in_thread(engine: Engine) -> None:
51
62
  """
52
63
  Runs migrations on the database in a separate thread.
53
64
  This is needed because depending on the context (notebook)
54
65
  the migration process can fail to execute in the main thread.
55
66
  """
56
- error_queue: Queue[Exception] = Queue()
57
- t = Thread(target=migrate, args=(url, error_queue))
67
+ error_queue: SimpleQueue[BaseException] = SimpleQueue()
68
+ t = Thread(target=migrate, args=(engine, error_queue))
58
69
  t.start()
59
70
  t.join()
60
71
 
@@ -11,7 +11,6 @@ from typing import Any, Dict, List, Optional, Sequence, TypedDict, Union
11
11
 
12
12
  import sqlalchemy as sa
13
13
  from alembic import op
14
- from phoenix.datetime_utils import normalize_datetime
15
14
  from sqlalchemy import (
16
15
  JSON,
17
16
  TIMESTAMP,
@@ -32,6 +31,8 @@ from sqlalchemy.orm import (
32
31
  mapped_column,
33
32
  )
34
33
 
34
+ from phoenix.datetime_utils import normalize_datetime
35
+
35
36
 
36
37
  class JSONB(JSON):
37
38
  # See https://docs.sqlalchemy.org/en/20/core/custom_types.html
@@ -113,7 +114,7 @@ class Base(DeclarativeBase):
113
114
  class UserRole(Base):
114
115
  __tablename__ = "user_roles"
115
116
  id: Mapped[int] = mapped_column(primary_key=True)
116
- role: Mapped[str] = mapped_column(unique=True)
117
+ name: Mapped[str] = mapped_column(unique=True)
117
118
 
118
119
 
119
120
  class User(Base):
@@ -150,10 +151,10 @@ async def insert_roles_and_users(connection: AsyncConnection) -> None:
150
151
  user to the `users` table.
151
152
  """
152
153
  await connection.execute(
153
- insert(UserRole).values([{"role": "SYSTEM"}, {"role": "ADMIN"}, {"role": "MEMBER"}])
154
+ insert(UserRole).values([{"name": "SYSTEM"}, {"name": "ADMIN"}, {"name": "MEMBER"}])
154
155
  )
155
- system_user_role_id = sa.select(UserRole.id).where(UserRole.role == "SYSTEM").scalar_subquery()
156
- admin_user_role_id = sa.select(UserRole.id).where(UserRole.role == "ADMIN").scalar_subquery()
156
+ system_user_role_id = sa.select(UserRole.id).where(UserRole.name == "SYSTEM").scalar_subquery()
157
+ admin_user_role_id = sa.select(UserRole.id).where(UserRole.name == "ADMIN").scalar_subquery()
157
158
  await connection.execute(
158
159
  insert(User).values(
159
160
  [
@@ -183,7 +184,7 @@ def upgrade() -> None:
183
184
  "user_roles",
184
185
  sa.Column("id", sa.Integer, primary_key=True),
185
186
  sa.Column(
186
- "role",
187
+ "name",
187
188
  sa.String,
188
189
  nullable=False,
189
190
  unique=True,
@@ -19,7 +19,6 @@ from sqlalchemy import (
19
19
  update,
20
20
  )
21
21
  from sqlalchemy.dialects import postgresql
22
- from sqlalchemy.ext.asyncio.engine import AsyncConnection
23
22
  from sqlalchemy.ext.compiler import compiles
24
23
  from sqlalchemy.orm import (
25
24
  DeclarativeBase,
@@ -111,11 +110,10 @@ LLM_TOKEN_COUNT_PROMPT = SpanAttributes.LLM_TOKEN_COUNT_PROMPT.split(".")
111
110
  LLM_TOKEN_COUNT_COMPLETION = SpanAttributes.LLM_TOKEN_COUNT_COMPLETION.split(".")
112
111
 
113
112
 
114
- async def get_token_counts_from_attributes(connection: AsyncConnection) -> None:
115
- """
116
- Gets token counts from attributes if present.
117
- """
118
- await connection.execute(
113
+ def upgrade() -> None:
114
+ op.add_column("spans", sa.Column("llm_token_count_prompt", sa.Integer, nullable=True))
115
+ op.add_column("spans", sa.Column("llm_token_count_completion", sa.Integer, nullable=True))
116
+ op.execute(
119
117
  update(Span).values(
120
118
  llm_token_count_prompt=Span.attributes[LLM_TOKEN_COUNT_PROMPT].as_float(),
121
119
  llm_token_count_completion=Span.attributes[LLM_TOKEN_COUNT_COMPLETION].as_float(),
@@ -123,12 +121,6 @@ async def get_token_counts_from_attributes(connection: AsyncConnection) -> None:
123
121
  )
124
122
 
125
123
 
126
- def upgrade() -> None:
127
- op.add_column("spans", sa.Column("llm_token_count_prompt", sa.Integer, nullable=True))
128
- op.add_column("spans", sa.Column("llm_token_count_completion", sa.Integer, nullable=True))
129
- op.run_async(get_token_counts_from_attributes)
130
-
131
-
132
124
  def downgrade() -> None:
133
125
  op.drop_column("spans", "llm_token_count_completion")
134
126
  op.drop_column("spans", "llm_token_count_prompt")
phoenix/db/models.py CHANGED
@@ -625,7 +625,7 @@ if ENABLE_AUTH:
625
625
  class UserRole(Base):
626
626
  __tablename__ = "user_roles"
627
627
  id: Mapped[int] = mapped_column(primary_key=True)
628
- role: Mapped[str] = mapped_column(unique=True)
628
+ name: Mapped[str] = mapped_column(unique=True)
629
629
  users: Mapped[List["User"]] = relationship("User", back_populates="role")
630
630
 
631
631
  class User(Base):
@@ -18,6 +18,7 @@ from phoenix.inferences.schema import (
18
18
  )
19
19
 
20
20
  logger = logging.getLogger(__name__)
21
+ logger.addHandler(logging.NullHandler())
21
22
 
22
23
 
23
24
  class InferencesRole(Enum):
@@ -34,6 +34,7 @@ from .schema import (
34
34
  from .validation import validate_inferences_inputs
35
35
 
36
36
  logger = logging.getLogger(__name__)
37
+ logger.addHandler(logging.NullHandler())
37
38
 
38
39
  # A schema like object. Not recommended to use this directly
39
40
  SchemaLike: TypeAlias = Any
@@ -10,6 +10,7 @@ import pandas as pd
10
10
  from phoenix.core.model_schema import Column
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
+ logger.addHandler(logging.NullHandler())
13
14
 
14
15
 
15
16
  @dataclass(frozen=True)
@@ -74,3 +74,17 @@ class Context(BaseContext):
74
74
  event_queue: CanPutItem[DmlEvent] = _NoOp()
75
75
  corpus: Optional[Model] = None
76
76
  read_only: bool = False
77
+ secret: Optional[str] = None
78
+
79
+ def get_secret(self) -> str:
80
+ """A type safe way to get the application secret. Throws an error if the secret is not set.
81
+
82
+ Returns:
83
+ str: the phoenix secret
84
+ """
85
+ if self.secret is None:
86
+ raise ValueError(
87
+ "Application secret not set."
88
+ " Please set the PHOENIX_SECRET environment variable and re-deploy the application."
89
+ )
90
+ return self.secret
@@ -1,5 +1,6 @@
1
1
  import strawberry
2
2
 
3
+ from phoenix.server.api.mutations.api_key_mutations import ApiKeyMutationMixin
3
4
  from phoenix.server.api.mutations.dataset_mutations import DatasetMutationMixin
4
5
  from phoenix.server.api.mutations.experiment_mutations import ExperimentMutationMixin
5
6
  from phoenix.server.api.mutations.export_events_mutations import ExportEventsMutationMixin
@@ -16,5 +17,6 @@ class Mutation(
16
17
  ExportEventsMutationMixin,
17
18
  SpanAnnotationMutationMixin,
18
19
  TraceAnnotationMutationMixin,
20
+ ApiKeyMutationMixin,
19
21
  ):
20
22
  pass