arize-phoenix 12.4.0__py3-none-any.whl → 12.5.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 (59) hide show
  1. {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.5.0.dist-info}/METADATA +1 -1
  2. {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.5.0.dist-info}/RECORD +59 -58
  3. phoenix/auth.py +8 -2
  4. phoenix/db/models.py +3 -3
  5. phoenix/server/api/auth.py +9 -0
  6. phoenix/server/api/context.py +2 -0
  7. phoenix/server/api/dataloaders/__init__.py +2 -0
  8. phoenix/server/api/dataloaders/dataset_dataset_splits.py +52 -0
  9. phoenix/server/api/input_types/ProjectSessionSort.py +158 -1
  10. phoenix/server/api/input_types/SpanSort.py +2 -1
  11. phoenix/server/api/input_types/UserRoleInput.py +1 -0
  12. phoenix/server/api/mutations/annotation_config_mutations.py +6 -6
  13. phoenix/server/api/mutations/api_key_mutations.py +13 -5
  14. phoenix/server/api/mutations/chat_mutations.py +3 -3
  15. phoenix/server/api/mutations/dataset_label_mutations.py +6 -6
  16. phoenix/server/api/mutations/dataset_mutations.py +8 -8
  17. phoenix/server/api/mutations/dataset_split_mutations.py +7 -7
  18. phoenix/server/api/mutations/experiment_mutations.py +2 -2
  19. phoenix/server/api/mutations/export_events_mutations.py +3 -3
  20. phoenix/server/api/mutations/model_mutations.py +4 -4
  21. phoenix/server/api/mutations/project_mutations.py +4 -4
  22. phoenix/server/api/mutations/project_session_annotations_mutations.py +4 -4
  23. phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +8 -4
  24. phoenix/server/api/mutations/prompt_label_mutations.py +7 -7
  25. phoenix/server/api/mutations/prompt_mutations.py +7 -7
  26. phoenix/server/api/mutations/prompt_version_tag_mutations.py +3 -3
  27. phoenix/server/api/mutations/span_annotations_mutations.py +5 -5
  28. phoenix/server/api/mutations/trace_annotations_mutations.py +4 -4
  29. phoenix/server/api/mutations/trace_mutations.py +3 -3
  30. phoenix/server/api/mutations/user_mutations.py +8 -5
  31. phoenix/server/api/routers/auth.py +2 -2
  32. phoenix/server/api/routers/v1/__init__.py +16 -1
  33. phoenix/server/api/routers/v1/annotation_configs.py +7 -1
  34. phoenix/server/api/routers/v1/datasets.py +48 -8
  35. phoenix/server/api/routers/v1/experiment_runs.py +7 -1
  36. phoenix/server/api/routers/v1/experiments.py +41 -5
  37. phoenix/server/api/routers/v1/projects.py +3 -31
  38. phoenix/server/api/routers/v1/users.py +0 -7
  39. phoenix/server/api/subscriptions.py +3 -3
  40. phoenix/server/api/types/Dataset.py +95 -6
  41. phoenix/server/api/types/Project.py +24 -68
  42. phoenix/server/app.py +2 -0
  43. phoenix/server/authorization.py +3 -1
  44. phoenix/server/bearer_auth.py +9 -0
  45. phoenix/server/jwt_store.py +8 -6
  46. phoenix/server/static/.vite/manifest.json +39 -39
  47. phoenix/server/static/assets/{components-BvsExS75.js → components-cwdYEs7B.js} +501 -394
  48. phoenix/server/static/assets/{index-iq8WDxat.js → index-Dc0vD1Rn.js} +1 -1
  49. phoenix/server/static/assets/{pages-Ckg4SLQ9.js → pages-BDkB3a_a.js} +577 -533
  50. phoenix/server/static/assets/{vendor-D2eEI-6h.js → vendor-Ce6GTAin.js} +1 -1
  51. phoenix/server/static/assets/{vendor-arizeai-kfOei7nf.js → vendor-arizeai-CSF-1Kc5.js} +1 -1
  52. phoenix/server/static/assets/{vendor-codemirror-1bq_t1Ec.js → vendor-codemirror-Bv8J_7an.js} +3 -3
  53. phoenix/server/static/assets/{vendor-recharts-DQ4xfrf4.js → vendor-recharts-DcLgzI7g.js} +1 -1
  54. phoenix/server/static/assets/{vendor-shiki-GGmcIQxA.js → vendor-shiki-BF8rh_7m.js} +1 -1
  55. phoenix/version.py +1 -1
  56. {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.5.0.dist-info}/WHEEL +0 -0
  57. {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.5.0.dist-info}/entry_points.txt +0 -0
  58. {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.5.0.dist-info}/licenses/IP_NOTICE +0 -0
  59. {arize_phoenix-12.4.0.dist-info → arize_phoenix-12.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 12.4.0
3
+ Version: 12.5.0
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://arize.com/docs/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -1,12 +1,12 @@
1
1
  phoenix/__init__.py,sha256=Sgb4r2MLoY2BbC9Caky5C0bwnOyiVOMHly2sRItmg3Q,5555
2
- phoenix/auth.py,sha256=2rw-2OR9BWF3_gHQM43Ip6wNZIt_9oEHiDezhKBujzQ,11999
2
+ phoenix/auth.py,sha256=bxYtmtUxCQnCPfIO88PzdNw0NlF50tvgl9yyrCl2skg,12298
3
3
  phoenix/config.py,sha256=EQYzCeib7o-63D2wSK8qTqdrYNEhJaUL5Axo9GJoErs,77844
4
4
  phoenix/datetime_utils.py,sha256=pRD-nzxXYKlMWNtd3r2tKGKfPFhwuJhfOAtlGLVAO60,8784
5
5
  phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
6
6
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
7
  phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
8
8
  phoenix/settings.py,sha256=2kHfT3BNOVd4dAO1bq-syEQbHSG8oX2-7NhOwK2QREk,896
9
- phoenix/version.py,sha256=HfLVXKB_isRuHq5O1cqtgrUnEms6bq-hPXvJw9iYVyk,23
9
+ phoenix/version.py,sha256=zMX_FM3cVT5krGMLJ7wIdD6aNccjxPXzb1MtTO9uB1g,23
10
10
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
12
12
  phoenix/core/model.py,sha256=qBFraOtmwCCnWJltKNP18DDG0mULXigytlFsa6YOz6k,4837
@@ -22,7 +22,7 @@ phoenix/db/enums.py,sha256=w3O5YuJEEzVTwVDZb8b2UUFhU8yK_GosF081VVrrno0,188
22
22
  phoenix/db/facilitator.py,sha256=4MW9ZQOHEJAeG8KUeiWbp-WBWrtIe5FWPohvGO8zqiE,20255
23
23
  phoenix/db/helpers.py,sha256=Inc3g_F7QtiTe-AW11j5EohUJVvDsHohyzIgObimjVI,21514
24
24
  phoenix/db/migrate.py,sha256=oUrXH8yEbcpL4eh09aSCuUiSrhFli0eT5D_j4ZmYChY,2797
25
- phoenix/db/models.py,sha256=ojmInqTNCm0GTv8sNXzUJBL7eBpcy-5NzqPeaZvlnpw,71269
25
+ phoenix/db/models.py,sha256=o14p35viN3iM9la1kFqVpY5RtJ8w5pszwm01ToOmRZk,71239
26
26
  phoenix/db/pg_config.py,sha256=h6mB7qF7t4Zk6VGvAiyefHGVu74o-yJynaWzeE39k9Y,6001
27
27
  phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  phoenix/db/insertion/constants.py,sha256=8wifm7X-1XvroZ__R2Gc96NsgLhTDn0zXl4lehlXtcA,70
@@ -102,13 +102,13 @@ phoenix/pointcloud/pointcloud.py,sha256=SN_1wXZcwKrtSnHGZLDZGx71orqE1WyVF7E-D58d
102
102
  phoenix/pointcloud/projectors.py,sha256=TQgwc9cJDjJkin1WZyZzgl3HsYrLLiyWD7Czy4jNW3U,1088
103
103
  phoenix/pointcloud/umap_parameters.py,sha256=db_WEPoamuWtopZx7tQfAXPnoE0MS8FkAV0_ThjEx_Q,1735
104
104
  phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
- phoenix/server/app.py,sha256=YTbBnxltAGamforPzLcDfg6Fb6ENgHHzkcPchghUA4o,50799
106
- phoenix/server/authorization.py,sha256=Te-dOFW--rdUoh55q8nod4cde83nfgoxadN8UH-7dWg,3085
107
- phoenix/server/bearer_auth.py,sha256=gBKJVlms42pSMAUpNUjfBuRJQF4IOAIWfVS1K_ikBrM,6527
105
+ phoenix/server/app.py,sha256=6j8bSoAaH5rI4ByGXxFjMfzQYrVDOK4TpXcqYSEMprA,50910
106
+ phoenix/server/authorization.py,sha256=Ws1bNyWLlTeRODcT6zNy8C5SB5WMROXrMYqzCDxTxZo,3114
107
+ phoenix/server/bearer_auth.py,sha256=IUL2b5O2J2oc593cy_S_SM0mCEL34r6Z9Zgia7CcS4k,6877
108
108
  phoenix/server/dml_event.py,sha256=HgUsIkzyXxCGasjnrqubegWbNaAcAgjrtWrKc3aRwxA,3245
109
109
  phoenix/server/dml_event_handler.py,sha256=71_iPcHiJ4E-8Z7sGL2j0vx_RpkmcMVEUFIBsWrdp-E,8483
110
110
  phoenix/server/grpc_server.py,sha256=THDdkMKXQEC3gZjFG2nUgXHFbUnWsRHgFM9oh5WtAX0,4758
111
- phoenix/server/jwt_store.py,sha256=B6uVildN_dQDTG_-aHHvuVSI7wIVK1yvED-_y6se2GU,16905
111
+ phoenix/server/jwt_store.py,sha256=a6WGmIKtKveByW9_JeSMmmYQO6JvfTudtpYyBYbsF14,17075
112
112
  phoenix/server/main.py,sha256=UBwxrQIEE7ci-SbE6GAlRYmbMHooI6JYG6sG-UpBFFs,18905
113
113
  phoenix/server/oauth2.py,sha256=faz8N-OX0LmgIguvRhOmCA5IPvsYjJ6fYcGpIfqgBT8,10012
114
114
  phoenix/server/prometheus.py,sha256=ovh6Hrw2mLUC6KddGydT0_lv-yK0upV9mL-T9UjqlcE,9373
@@ -121,20 +121,21 @@ phoenix/server/types.py,sha256=j8erl9iRNaR8t0DCQG84-uDVbHy9Qnm7T2EuTtDNNsU,8013
121
121
  phoenix/server/utils.py,sha256=zTgY07W9GOpAFvIIPVBfXAGQb6kwGla2lhj1VGTCeIU,3057
122
122
  phoenix/server/api/README.md,sha256=Pyq1PLPgTzXAswrfIhGXrjI3Skq8it2jTVnanT6Ba4Q,1162
123
123
  phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
- phoenix/server/api/auth.py,sha256=AyYhnZIbY9ALVjg2K6aC2UXSa3Pva5GVDBXyaZ3nD3o,2749
124
+ phoenix/server/api/auth.py,sha256=lDj289lNGY0-HqzlNyvWwPXjF3qHiSsOuvCJNIAbU0k,3072
125
125
  phoenix/server/api/auth_messages.py,sha256=15oqogBNS2BgJLLDecfXz62G9LdiOAEyzPv6jX9BxYE,1912
126
- phoenix/server/api/context.py,sha256=rdjGb0Ce-XBFVF5lj-lA8VoyKmrrPpLdU_BKT0qhFyQ,10450
126
+ phoenix/server/api/context.py,sha256=c5xVGdGAoysNOoAqGNUXtn2wOFcKbERPJ7-26HIxbpI,10545
127
127
  phoenix/server/api/exceptions.py,sha256=9gB4nBRNX6k4_fsQZ12yxw6Tw53h_915l06DYK-qkPQ,1442
128
128
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
129
129
  phoenix/server/api/queries.py,sha256=eZ12poXJ08Pla-DIW8v5dS9gWKdIbS-WO0Df-iGbLOg,67341
130
130
  phoenix/server/api/schema.py,sha256=fcs36xQwFF_Qe41_5cWR8wYpDvOrnbcyTeo5WNMbDsA,1702
131
- phoenix/server/api/subscriptions.py,sha256=5J5_B6FUZav4UBzWETdcGNjClZa7-T1d7vxxeQCg63s,26167
131
+ phoenix/server/api/subscriptions.py,sha256=qrLN2p0gYV7tluKSqOsHfWZTB9ZqhjviTqJPjZOHGko,26206
132
132
  phoenix/server/api/utils.py,sha256=quCBRcusc6PUq9tJq7M8PgwFZp7nXgVAxtbw8feribY,833
133
- phoenix/server/api/dataloaders/__init__.py,sha256=yDuF2Ci9ab8a-m3b4q-eVLXo9X3CaFX5SGgpZ35BGHk,8129
133
+ phoenix/server/api/dataloaders/__init__.py,sha256=b2eVMs8ZALHmsu8oJLTIB2gAIRniWUQpZDc6lwketmE,8234
134
134
  phoenix/server/api/dataloaders/annotation_configs_by_project.py,sha256=_Nfiug9o01JimU3Z0LpZJ0uaMCjchXomyt_dYAxPFRY,1178
135
135
  phoenix/server/api/dataloaders/annotation_summaries.py,sha256=0b23-bucBKyL25RWb2QzCNJjQzrq403qMmHKUVD5W4M,14377
136
136
  phoenix/server/api/dataloaders/average_experiment_repeated_run_group_latency.py,sha256=BSNyrwuNadQ16-2g0nGixrB5LyDqlTLeM2bKikyIagY,1860
137
137
  phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=_wEcC47zOtLFMYTfyaFWA93TlAVC3kAPZhMnRO-xB24,1809
138
+ phoenix/server/api/dataloaders/dataset_dataset_splits.py,sha256=-I622QubefUY4aap4MsUeC5aDwUeJcJEwEfMKsMg8Zs,1906
138
139
  phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=MqRBkT3AE6b6A7uucFYfkH86eXMAyYJDFyg3a8tx-GM,4547
139
140
  phoenix/server/api/dataloaders/dataset_example_spans.py,sha256=z_MFquqAcJ9wat7BBp7MVeJ9BYuu2EZEdaog52iWDno,1390
140
141
  phoenix/server/api/dataloaders/dataset_example_splits.py,sha256=u1XVZPvoB6qevuYN0kbKUnCFJsuvwBGsCZV8jfPAmwY,1524
@@ -242,63 +243,63 @@ phoenix/server/api/input_types/PatchDatasetExamplesInput.py,sha256=_uMqkAInhLDvz
242
243
  phoenix/server/api/input_types/PatchDatasetInput.py,sha256=OURtTVY8Z_oFEDtKwT1LCMaOK5D4QYo5TVQ6mDrex-g,328
243
244
  phoenix/server/api/input_types/PerformanceMetricInput.py,sha256=4SG5AymxV2dMeCrK7eREThdt9SuC43irMYZtY-Oq-bg,658
244
245
  phoenix/server/api/input_types/ProjectFilter.py,sha256=w3IimMXcNmMkrQ6h89-Yx6uh21r2wj1jci1nPZEDEhQ,260
245
- phoenix/server/api/input_types/ProjectSessionSort.py,sha256=KZzEtOMpcxtP11brL4fXUAY_RLAK-Ul4luAWwVKnQgY,1043
246
+ phoenix/server/api/input_types/ProjectSessionSort.py,sha256=erUJ1O0i9SmZS5fid6vtFg6rYU_NdL_31Y4ae3avw2I,7178
246
247
  phoenix/server/api/input_types/ProjectSort.py,sha256=ZTT-InFB6NvInDwLuivyHe9PxR5nsmQ8aXCHAPjZm9k,329
247
248
  phoenix/server/api/input_types/PromptFilter.py,sha256=f2F7fDlYRsNJp_rKkmvpgUt9rfgr_e-dyZxuHX8YfkU,256
248
249
  phoenix/server/api/input_types/PromptTemplateOptions.py,sha256=8ZJdH1F9fExcdH9dF8SJ29WycCvtEpK-Z6dZwFO7KgQ,232
249
250
  phoenix/server/api/input_types/PromptVersionInput.py,sha256=6iFWf2Ye9K1dwL1810L-wUTLkMtOIHemJTxar4xF4kw,3911
250
251
  phoenix/server/api/input_types/SpanAnnotationSort.py,sha256=T5pAGzmh4MiJp9JMAzNDByFVTczfw02FH4WFWwFezyI,361
251
- phoenix/server/api/input_types/SpanSort.py,sha256=1AHrqx3HuVKsp9DSaDsQMAyid4Au3kqY38mE9x0nPBU,7552
252
+ phoenix/server/api/input_types/SpanSort.py,sha256=aybgSeuJvCsQf4yRDEDildHgE6aNYq5vnXTynRzD-eY,7612
252
253
  phoenix/server/api/input_types/TimeBinConfig.py,sha256=s4p0SNTGRY6rbHfZhEMwmon5zX85j-DbN06GkapF6jg,516
253
254
  phoenix/server/api/input_types/TimeRange.py,sha256=pwhC2jx6dFIgT0qFfnO68qiJp9-m7Je5QkNscNsuVxA,700
254
255
  phoenix/server/api/input_types/TraceAnnotationSort.py,sha256=BzwiUnMh2VsgQYnhDlbJ6ljHugqIS4YDUlYzvq_tl3o,365
255
256
  phoenix/server/api/input_types/UpdateAnnotationInput.py,sha256=ZhWmu6eQ2jJ9_e99mN_eIe1yB2VG8k3quy6cTyBqDTo,1227
256
- phoenix/server/api/input_types/UserRoleInput.py,sha256=xxhFe0ITZOgRVEJbVem_W6F1Ip_H6xDENdQqMMx-kKE,129
257
+ phoenix/server/api/input_types/UserRoleInput.py,sha256=xowBkijREtDpcc909xXarpxfLhxMC88Xl0bZzZGv6Sw,151
257
258
  phoenix/server/api/input_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
258
259
  phoenix/server/api/mutations/__init__.py,sha256=83V5Ia8ijsajSLo_gzAuHXo4hgDlUGLIUrerxzKKVn8,2385
259
- phoenix/server/api/mutations/annotation_config_mutations.py,sha256=i7NsQhYICcQ-I-tnFjGtVAYc8WVmMBacmRaqHWJ25t4,15433
260
- phoenix/server/api/mutations/api_key_mutations.py,sha256=nfnRjALCaQMi_jIbEPW4G3Dn3tPnmZVU11tpBbBijGA,6242
261
- phoenix/server/api/mutations/chat_mutations.py,sha256=HoO1V_ZvJ_TRIPCftmwyVrD3AaIsznWczOTZB9euO2Q,25306
262
- phoenix/server/api/mutations/dataset_label_mutations.py,sha256=nVw2IaycdscAX2CJ1Jk4icRNvu61hWvb1UeN0sgC9Tk,11582
263
- phoenix/server/api/mutations/dataset_mutations.py,sha256=D7LULYXnQeb7kep_b5SmSEGYxZXVt5U9gvOvwd0aI2E,28033
264
- phoenix/server/api/mutations/dataset_split_mutations.py,sha256=RgFy2i02az-ckGkQ89VljTVnGXsUmr5Hvv7j7QRebQI,17324
265
- phoenix/server/api/mutations/experiment_mutations.py,sha256=p3CoLAa8nFPa3D759Y2A7De_PVJNGOL98mA3HoZBrRQ,3188
266
- phoenix/server/api/mutations/export_events_mutations.py,sha256=xoDnVWC7eA_8wNQP0-oyiHojyUZ0EhVVSrsAnztetC0,3993
267
- phoenix/server/api/mutations/model_mutations.py,sha256=eh-QIKww3EDrDewS3NTWTqnE2bwLJJ5WgRFvSPRksZg,7199
268
- phoenix/server/api/mutations/project_mutations.py,sha256=PQCwODI0VXk9Rllxdar4bNEyaYb1rJiMHXTqol-cFYY,4569
269
- phoenix/server/api/mutations/project_session_annotations_mutations.py,sha256=xeBI8LBB0o9v_yrs09rifjl1o1QppHN0Q4klt4ExbIE,7070
270
- phoenix/server/api/mutations/project_trace_retention_policy_mutations.py,sha256=AqBe8TBxlXdIL56Afs4FIBqkI0bEgf-v9bHlbc-O6VI,9839
271
- phoenix/server/api/mutations/prompt_label_mutations.py,sha256=FP3UWPynWHfSRgHlMliDx9LS3DF7dY3EJGPPV8hVIyY,7254
272
- phoenix/server/api/mutations/prompt_mutations.py,sha256=Yg-6L2PiKUZfFyNarptu3OdE0uA2_Nyl3VrLVP8FJ9Y,12114
273
- phoenix/server/api/mutations/prompt_version_tag_mutations.py,sha256=t77osYb5he2Am4UeNis7pzY9MnaA9PNEQhsQelRH8k8,5767
274
- phoenix/server/api/mutations/span_annotations_mutations.py,sha256=LQPcODp7-ZobXspjmtLaamyQa8UkTONC_va-ST9r-k8,15015
275
- phoenix/server/api/mutations/trace_annotations_mutations.py,sha256=zWoMfOMSQZqw7gZl7Le2PRojkDcG_KOiP1iIuqZpZ8Q,11971
276
- phoenix/server/api/mutations/trace_mutations.py,sha256=AvtQAfqNWBQpJOZm4e0DZFimhVJ6HQHtSSZtezRadCo,4698
277
- phoenix/server/api/mutations/user_mutations.py,sha256=6mwMx5I5c_VgUutOLrN9LSMcyPLgXzNaT0XT24ZwNWM,15473
260
+ phoenix/server/api/mutations/annotation_config_mutations.py,sha256=ZcjWlJ88B_jevoESmOtmO0l-SUEbtAwxwP1KpWTmYqQ,15511
261
+ phoenix/server/api/mutations/api_key_mutations.py,sha256=3djEPrVOwF7oN3C46WEROWqiBi0EZnue7dTQDAxwBKo,6526
262
+ phoenix/server/api/mutations/chat_mutations.py,sha256=EQRSGpUdlfbW1pDdCFCtMOian_CpGhhd3ZMY1qsmAhA,25345
263
+ phoenix/server/api/mutations/dataset_label_mutations.py,sha256=Paq1zsWyrAXTcfPvX5Bn53LDt1rIIrJtAo5XlRP-0Ts,11660
264
+ phoenix/server/api/mutations/dataset_mutations.py,sha256=BsBW2epV3gtgnO2fn3lJP9uX2qOZEY6gy0UW1UEgpUA,28137
265
+ phoenix/server/api/mutations/dataset_split_mutations.py,sha256=Mbmr6LyqqoaLfB4rwMrx2V0GICHlcJ34hyj6c1k7tvk,17415
266
+ phoenix/server/api/mutations/experiment_mutations.py,sha256=_fWkKl3VEMF4w885vIuh8zjH9SOhlXc4QaHzGLgBnuY,3214
267
+ phoenix/server/api/mutations/export_events_mutations.py,sha256=a9soJCXuFQ21wJa2FdbeMh7pPI7EkFzVI50nwX-Y2XI,4032
268
+ phoenix/server/api/mutations/model_mutations.py,sha256=FPr_FunvLqpzEWVwiEZ3Yh6iEISzWh151gFK8maFczY,7251
269
+ phoenix/server/api/mutations/project_mutations.py,sha256=iUzdzdz9rS98Hu5MxvjVjJAQlzJyaWt2Q7cJuy4RhNI,4621
270
+ phoenix/server/api/mutations/project_session_annotations_mutations.py,sha256=xY0PNOH-7B7nCVMBhJrqKk9eLfJ0RlMc3oFAz-FLL_w,7122
271
+ phoenix/server/api/mutations/project_trace_retention_policy_mutations.py,sha256=9gc6GfUWuXssAlEuHVViQItW5Lv5MrmTx8569d8jRQ4,9919
272
+ phoenix/server/api/mutations/prompt_label_mutations.py,sha256=OG_zPaS8dTr8IQT3Jguw3c66RzptEN5VotvjeuCZRNY,7362
273
+ phoenix/server/api/mutations/prompt_mutations.py,sha256=l4-zWtaZkazzE99pHo6z1hoX5BbEG3yKrV5w1cHC3t0,12222
274
+ phoenix/server/api/mutations/prompt_version_tag_mutations.py,sha256=oV7ClP6R3v7EjMVl4mKzPPQ_GC9Xs_tKMT-LfHDa04I,5806
275
+ phoenix/server/api/mutations/span_annotations_mutations.py,sha256=G4w2LdQwrAT-juKcf6NME3XqnCHuKT3Al8dFJWfz1S4,15080
276
+ phoenix/server/api/mutations/trace_annotations_mutations.py,sha256=vzJnmhMB_m1VbIewSaqD9xB5OAATHDtF71dsQ4f4iHU,12023
277
+ phoenix/server/api/mutations/trace_mutations.py,sha256=_lISuai_tdfmf4x1D8bS_NMv2ZV_1OmVKLoDffbYZ38,4737
278
+ phoenix/server/api/mutations/user_mutations.py,sha256=hqblu7JI-q3bh1TiRJyRIw10T9A61wWm6szoUC6ph1Y,15632
278
279
  phoenix/server/api/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
279
280
  phoenix/server/api/openapi/main.py,sha256=yKdzJYI4cxy_1mFcK4_7YObIcuRviBIfwNjB23RG14k,461
280
281
  phoenix/server/api/openapi/schema.py,sha256=WGmHWSIyJhtc5EIh_M3vlXU-EgHkFuTlyVofgS0kj1I,529
281
282
  phoenix/server/api/routers/__init__.py,sha256=YIzHsIFOOXuCRbDkMUHx-McrANFJK5UfUn6a4BNIzmo,277
282
- phoenix/server/api/routers/auth.py,sha256=3-EITfKlqQPi35lqGUi1IGvmGG-3Zz25TQSx1ArZz6E,11336
283
+ phoenix/server/api/routers/auth.py,sha256=_rb0_GWm-HSd0RPPCYl_7n8Hpe7eEI2qVq-QVKyd6SU,11350
283
284
  phoenix/server/api/routers/embeddings.py,sha256=BpZGJee0pdL0W5Rp1L0b30dEtZTgJeVqXky8LgZ0ZXw,898
284
285
  phoenix/server/api/routers/oauth2.py,sha256=0W1leIdxRRHGBpTcmrfoKDtDVQzMqHiFDqFUoUFEF1k,33509
285
286
  phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
286
- phoenix/server/api/routers/v1/__init__.py,sha256=2vTXYJVgjdc_jN0Vro-DxId-4Yz45hTZSf2T-2I1-Mg,2803
287
- phoenix/server/api/routers/v1/annotation_configs.py,sha256=j8YsOAnqMERWQChU1KIQt6sk5-8VGsxsgK8LsTidtaY,15597
287
+ phoenix/server/api/routers/v1/__init__.py,sha256=C4T5F9gzb3cbaWWqR_0jysh2AhRVS_7qcceE6FD-Ojo,3320
288
+ phoenix/server/api/routers/v1/annotation_configs.py,sha256=g4XpQAAF3rt_4p0MHPsdCBiJGKCIoAHAJUQrked-eHE,15779
288
289
  phoenix/server/api/routers/v1/annotations.py,sha256=ZZnh8hoOjq1rFnytivHwfIWbS1jmDZeHULPC4qV_gQM,23261
289
- phoenix/server/api/routers/v1/datasets.py,sha256=L9d5Q29HLDhL9HdkBZqiQ_yO-legb0VVB2-3dTZxl3g,37484
290
+ phoenix/server/api/routers/v1/datasets.py,sha256=9SRQDt4KGVOjLI8gJvdwWBsYljbeymg6yIoKRXLpgCM,38615
290
291
  phoenix/server/api/routers/v1/documents.py,sha256=J6fvKipprdJJoB7Pr8dU1f7z5Bym5Ehh_sH_vtTP3R0,5667
291
292
  phoenix/server/api/routers/v1/evaluations.py,sha256=BpY8vWBNAdBB3Qe_cHpkSHVfRjU0SUfOKdI46JicXJE,12578
292
293
  phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=qd7r8q0GXWUV_j8vx1ca-5WCazPFAf8nrKHNBqy9irk,5171
293
- phoenix/server/api/routers/v1/experiment_runs.py,sha256=KG3aQmmsNDYJZLURSGumEEY8LulSZFomqDdpZymRaIQ,8125
294
- phoenix/server/api/routers/v1/experiments.py,sha256=FEW2tqwFp2xCli7hErLqpWfQqIOzb-D0hVbjzsSY6vM,20601
294
+ phoenix/server/api/routers/v1/experiment_runs.py,sha256=Z7pzvIms3_iSYUWELY7W-yz3dJnhN0AxJwdOb2JsCa0,8309
295
+ phoenix/server/api/routers/v1/experiments.py,sha256=OvD1JCw1Mb82t4VXXedZZBTt3FjNGdToaXYcUIKGsFY,21733
295
296
  phoenix/server/api/routers/v1/models.py,sha256=p3gJN-9SWiUYTUTft4bZMsZVCBNTb4nN1Foy68eRZzQ,1997
296
- phoenix/server/api/routers/v1/projects.py,sha256=_9WVE5_37ebieAdkkCcGkgfUEzAMeZgJk6nJos4ZK5k,12391
297
+ phoenix/server/api/routers/v1/projects.py,sha256=E5yoL6KbjuHCqlfNc2-hkoG_7JKOI2c-xpbackS-Cys,11244
297
298
  phoenix/server/api/routers/v1/prompts.py,sha256=D4pg8SSuGDEHTwDzZU9UG0ymRNDnIuuFf4zp4EeTs5Q,25920
298
299
  phoenix/server/api/routers/v1/sessions.py,sha256=0rugljeHFyMOIFtRe8CkPbjBI1_49ldMPowzNrmQJf0,4133
299
300
  phoenix/server/api/routers/v1/spans.py,sha256=1qSP4YRqO5W3yxx-28EHBy6tYJrA_i7CLQ-xEfN9XSU,47674
300
301
  phoenix/server/api/routers/v1/traces.py,sha256=2USf0F0SFwU8GQ3lUMooMFnKlzAZwcahCz3GcIXeOic,10003
301
- phoenix/server/api/routers/v1/users.py,sha256=VCsu32RFnYRi9iR6hoPd_v72A52YOPPVmNbw9KBnSGE,11832
302
+ phoenix/server/api/routers/v1/users.py,sha256=SCJbYyKhiCH4BY_Luv6eixAWnrL9xHDMfqXKhm2iBAM,11650
302
303
  phoenix/server/api/routers/v1/utils.py,sha256=Z4rd3dvxPYDNR0ApqH6wZ_bk5wyywaI19l0_ibqm5pk,4812
303
304
  phoenix/server/api/types/Annotation.py,sha256=gsl8CwjIbDUbZRj4d9USwZ_w_Tkz4i7zuZh9ftV80jA,1132
304
305
  phoenix/server/api/types/AnnotationConfig.py,sha256=TPukZUgvFC17W93Vnme21EhswasBMR-ZiuSWteiWZOU,3891
@@ -314,7 +315,7 @@ phoenix/server/api/types/CostBreakdown.py,sha256=yw9dlb0blGIB_dWNP8yEvDHJztHjpiV
314
315
  phoenix/server/api/types/CreateDatasetPayload.py,sha256=R-6zCmuD0f76RU9Giu78xwTHlASQs6Aq8yzvX1Kxc3g,140
315
316
  phoenix/server/api/types/CronExpression.py,sha256=R7oxuSSX_eTUHQWaoaSueQqWDmkkHr5dBKRN6q-6ROk,331
316
317
  phoenix/server/api/types/DataQualityMetric.py,sha256=Aieg3bHeBFaAf4mqeRcH1zT04sXAtQD8ATSHJt7FaBQ,1538
317
- phoenix/server/api/types/Dataset.py,sha256=zDmvMl3J2pIX4VwjX-PAek5jC1_jk7ME-p0wHXW3Des,12991
318
+ phoenix/server/api/types/Dataset.py,sha256=9e3X4r0Z7GL7axi7JQk67eTCAZNMw_7UOja_JoaSmJo,16819
318
319
  phoenix/server/api/types/DatasetExample.py,sha256=9xEdDVj8rNK3LOs98Ekm67sz56yfpjj9Vn9CXIndW74,5650
319
320
  phoenix/server/api/types/DatasetExampleRevision.py,sha256=c-jWR6dTguEZTm54IMlFr0Ic84I3nefyDnZb7nF5hnI,874
320
321
  phoenix/server/api/types/DatasetExperimentAnnotationSummary.py,sha256=EVXz6zfbdYsU5SZ6FUrAA_VQqQCnBE_mbKgmAmFoDLI,195
@@ -357,7 +358,7 @@ phoenix/server/api/types/ModelInterface.py,sha256=Qe7H23wDb_Q2-HmeY2t0R5Jsn4aAfY
357
358
  phoenix/server/api/types/NumericRange.py,sha256=afEjgF97Go_OvmjMggbPBt-zGM8IONewAyEiKEHRds0,192
358
359
  phoenix/server/api/types/PerformanceMetric.py,sha256=KFkmJDqP43eDUtARQOUqR7NYcxvL6Vh2uisHWU6H3ko,387
359
360
  phoenix/server/api/types/PlaygroundModel.py,sha256=IqJFxsAAJMRyaFI9ryI3GQrpFOJ5Llf6kIutEO-tFvM,321
360
- phoenix/server/api/types/Project.py,sha256=D6S4hgcSXD1V2brV1x-NImWfoTcU4u9BceIBX8S1pvY,72873
361
+ phoenix/server/api/types/Project.py,sha256=r-Bs_9lA8Ed8xdwobdMELCrMOdwek8m5VPYGEiNz-tI,70854
361
362
  phoenix/server/api/types/ProjectSession.py,sha256=YvRqj9qXXY4FvYN9Nhie9qdHcNCEPz7SoBdflrbLGRk,9795
362
363
  phoenix/server/api/types/ProjectSessionAnnotation.py,sha256=yerdFlW_dhCxDeoyE-75n6I_k4uUWn0m3S4XSdplS6E,2102
363
364
  phoenix/server/api/types/ProjectTraceRetentionPolicy.py,sha256=tYy2kgalPDyuaYZr0VUHjH0YpXaiF_QOzg5yfaV_c7c,3782
@@ -428,16 +429,16 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
428
429
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
429
430
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
430
431
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
431
- phoenix/server/static/.vite/manifest.json,sha256=-6rZ4VH8u0MiGdfYaHJUSC-Y9kxXSyRZBk_r6XNjwfc,2328
432
- phoenix/server/static/assets/components-BvsExS75.js,sha256=c1BjHL2AZpq6dJoE-W-13R6DwLVosOk0_v6UMc2l-58,723377
433
- phoenix/server/static/assets/index-iq8WDxat.js,sha256=fUQRYa8X34s8pIA6EDPNAztEErm3VadYVZxdS3MtW00,63680
434
- phoenix/server/static/assets/pages-Ckg4SLQ9.js,sha256=LAO5c9t6TPyCPzpnqb8ZMfzZ_Ys6XAwXbPULg77qauo,1340969
432
+ phoenix/server/static/.vite/manifest.json,sha256=silunyyOmVAGQps_jL9aTV8d03ZDtMiKo-42b52u49Q,2328
433
+ phoenix/server/static/assets/components-cwdYEs7B.js,sha256=47qfw-bmftAyo9ANA81Ot24VTAU1kI35jML_g92NJt4,741688
434
+ phoenix/server/static/assets/index-Dc0vD1Rn.js,sha256=zVCMmPbr4UA6BhhArmzav1NSOcjFv76EqqSbbUedLYs,63680
435
+ phoenix/server/static/assets/pages-BDkB3a_a.js,sha256=CgzTVVYSyPnUWbQs_W0uf7fKDcYjklApAUDtiVyQ-zg,1352672
435
436
  phoenix/server/static/assets/vendor-BGzfc4EU.css,sha256=Nx5Lmx-bqYR7nsO_O4kEBcrJ8cwknWjZ6seHN3_s4UQ,3171
436
- phoenix/server/static/assets/vendor-D2eEI-6h.js,sha256=DcZ_ov-x3PP13qfDh2X0hhQTuuSnxoMnYVBW98YBo0Q,2709850
437
- phoenix/server/static/assets/vendor-arizeai-kfOei7nf.js,sha256=AlUQvzFvgUY2d5qzujvi4N7VXbhmpcnrKAYk9Ilpzt4,107788
438
- phoenix/server/static/assets/vendor-codemirror-1bq_t1Ec.js,sha256=cjHHniUz2eOaXgg3iPcyd3d8hRz_2z7tW_UTPiMyGiA,413211
439
- phoenix/server/static/assets/vendor-recharts-DQ4xfrf4.js,sha256=tTNG6AAxOGuPbEnjQkr3EzR7COVhDnN37QJFV6BNQg8,231652
440
- phoenix/server/static/assets/vendor-shiki-GGmcIQxA.js,sha256=U357g2RSPGwucCoww2yscGQcLyWIcP3EQxlkMgR9CJg,305160
437
+ phoenix/server/static/assets/vendor-Ce6GTAin.js,sha256=k2-KQcgnT72FQrld80rZ4i6xwZFLNOXYnzoxmafJ6dM,2709850
438
+ phoenix/server/static/assets/vendor-arizeai-CSF-1Kc5.js,sha256=QzLkcp6Qyc8cBmTC-_HMBFskV7RH5C_gJL01tg5D398,107788
439
+ phoenix/server/static/assets/vendor-codemirror-Bv8J_7an.js,sha256=OHKLBrrONfwV0plQcCulUS0pgeKYDaT_ZvYxxcwZYtE,413211
440
+ phoenix/server/static/assets/vendor-recharts-DcLgzI7g.js,sha256=1ncLhLxQPfQC_7j90ms3HMxU_OLIWlna70T1kyoTDR8,231652
441
+ phoenix/server/static/assets/vendor-shiki-BF8rh_7m.js,sha256=YcEirsQMcEwHSIUVn7A7Y65zo9Qs3wQxdY5J-hG18D8,305160
441
442
  phoenix/server/static/assets/vendor-three-BLWp5bic.js,sha256=vfSCVXS20jA0Ceo_O0mDxYBcROinWMdPE6RR4JXmtec,620972
442
443
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
443
444
  phoenix/server/templates/index.html,sha256=_iKIyXEDDr5cTTnrUCjCd617U6Alc1k-IXtdKSt8g14,7215
@@ -477,9 +478,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
477
478
  phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
478
479
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
479
480
  phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
480
- arize_phoenix-12.4.0.dist-info/METADATA,sha256=U2Q5WCy3t7fYBMAbfHOf6SFofXypJ699MtmT19p9rNw,34069
481
- arize_phoenix-12.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
482
- arize_phoenix-12.4.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
483
- arize_phoenix-12.4.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
484
- arize_phoenix-12.4.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
485
- arize_phoenix-12.4.0.dist-info/RECORD,,
481
+ arize_phoenix-12.5.0.dist-info/METADATA,sha256=8noiF2OI1hEI45XtrnDzongEmwKPvXAfSFkeMpPXgmY,34069
482
+ arize_phoenix-12.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
483
+ arize_phoenix-12.5.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
484
+ arize_phoenix-12.5.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
485
+ arize_phoenix-12.5.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
486
+ arize_phoenix-12.5.0.dist-info/RECORD,,
phoenix/auth.py CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import re
4
4
  from dataclasses import dataclass
5
- from datetime import datetime, timedelta
5
+ from datetime import datetime, timedelta, timezone
6
6
  from enum import Enum, auto
7
7
  from hashlib import pbkdf2_hmac
8
8
  from typing import Any, Literal, Optional, Protocol
@@ -331,7 +331,13 @@ class ClaimSet:
331
331
 
332
332
  @property
333
333
  def status(self) -> ClaimSetStatus:
334
- if self.expiration_time and self.expiration_time.timestamp() < datetime.now().timestamp():
334
+ # Per JWT RFC 7519 Section 4.1.4, the expiration time identifies the time
335
+ # "on or after which" the JWT must not be accepted. Use <= for inclusive check.
336
+ # https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
337
+ if (
338
+ self.expiration_time
339
+ and self.expiration_time.timestamp() <= datetime.now(timezone.utc).timestamp()
340
+ ):
335
341
  return ClaimSetStatus.EXPIRED
336
342
  if self.token_id is not None and self.subject is not None:
337
343
  return ClaimSetStatus.VALID
phoenix/db/models.py CHANGED
@@ -1607,7 +1607,7 @@ class PasswordResetToken(HasId):
1607
1607
  )
1608
1608
  user: Mapped["User"] = relationship("User", back_populates="password_reset_token")
1609
1609
  created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
1610
- expires_at: Mapped[Optional[datetime]] = mapped_column(UtcTimeStamp, nullable=False, index=True)
1610
+ expires_at: Mapped[datetime] = mapped_column(UtcTimeStamp, nullable=False, index=True)
1611
1611
  __table_args__ = (dict(sqlite_autoincrement=True),)
1612
1612
 
1613
1613
 
@@ -1619,7 +1619,7 @@ class RefreshToken(HasId):
1619
1619
  )
1620
1620
  user: Mapped["User"] = relationship("User", back_populates="refresh_tokens")
1621
1621
  created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
1622
- expires_at: Mapped[Optional[datetime]] = mapped_column(UtcTimeStamp, nullable=False, index=True)
1622
+ expires_at: Mapped[datetime] = mapped_column(UtcTimeStamp, nullable=False, index=True)
1623
1623
  __table_args__ = (dict(sqlite_autoincrement=True),)
1624
1624
 
1625
1625
 
@@ -1631,7 +1631,7 @@ class AccessToken(HasId):
1631
1631
  )
1632
1632
  user: Mapped["User"] = relationship("User", back_populates="access_tokens")
1633
1633
  created_at: Mapped[datetime] = mapped_column(UtcTimeStamp, server_default=func.now())
1634
- expires_at: Mapped[Optional[datetime]] = mapped_column(UtcTimeStamp, nullable=False, index=True)
1634
+ expires_at: Mapped[datetime] = mapped_column(UtcTimeStamp, nullable=False, index=True)
1635
1635
  refresh_token_id: Mapped[int] = mapped_column(
1636
1636
  ForeignKey("refresh_tokens.id", ondelete="CASCADE"),
1637
1637
  index=True,
@@ -22,6 +22,15 @@ class IsNotReadOnly(Authorization):
22
22
  return not info.context.read_only
23
23
 
24
24
 
25
+ class IsNotViewer(Authorization):
26
+ message = "Viewers cannot perform this action"
27
+
28
+ def has_permission(self, source: Any, info: Info, **kwargs: Any) -> bool:
29
+ if not info.context.auth_enabled:
30
+ return True
31
+ return isinstance((user := info.context.user), PhoenixUser) and not user.is_viewer
32
+
33
+
25
34
  class IsLocked(BasePermission):
26
35
  """
27
36
  Permission class that restricts data-modifying operations when insufficient storage.
@@ -20,6 +20,7 @@ from phoenix.server.api.dataloaders import (
20
20
  AverageExperimentRepeatedRunGroupLatencyDataLoader,
21
21
  AverageExperimentRunLatencyDataLoader,
22
22
  CacheForDataLoaders,
23
+ DatasetDatasetSplitsDataLoader,
23
24
  DatasetExampleRevisionsDataLoader,
24
25
  DatasetExamplesAndVersionsByExperimentRunDataLoader,
25
26
  DatasetExampleSpansDataLoader,
@@ -101,6 +102,7 @@ class DataLoaders:
101
102
  dataset_example_revisions: DatasetExampleRevisionsDataLoader
102
103
  dataset_example_spans: DatasetExampleSpansDataLoader
103
104
  dataset_labels: DatasetLabelsDataLoader
105
+ dataset_dataset_splits: DatasetDatasetSplitsDataLoader
104
106
  dataset_examples_and_versions_by_experiment_run: (
105
107
  DatasetExamplesAndVersionsByExperimentRunDataLoader
106
108
  )
@@ -10,6 +10,7 @@ from .average_experiment_repeated_run_group_latency import (
10
10
  AverageExperimentRepeatedRunGroupLatencyDataLoader,
11
11
  )
12
12
  from .average_experiment_run_latency import AverageExperimentRunLatencyDataLoader
13
+ from .dataset_dataset_splits import DatasetDatasetSplitsDataLoader
13
14
  from .dataset_example_revisions import DatasetExampleRevisionsDataLoader
14
15
  from .dataset_example_spans import DatasetExampleSpansDataLoader
15
16
  from .dataset_example_splits import DatasetExampleSplitsDataLoader
@@ -84,6 +85,7 @@ __all__ = [
84
85
  "AverageExperimentRepeatedRunGroupLatencyDataLoader",
85
86
  "AverageExperimentRunLatencyDataLoader",
86
87
  "CacheForDataLoaders",
88
+ "DatasetDatasetSplitsDataLoader",
87
89
  "DatasetExampleRevisionsDataLoader",
88
90
  "DatasetExampleSpansDataLoader",
89
91
  "DatasetExamplesAndVersionsByExperimentRunDataLoader",
@@ -0,0 +1,52 @@
1
+ from sqlalchemy import select
2
+ from strawberry.dataloader import DataLoader
3
+ from typing_extensions import TypeAlias
4
+
5
+ from phoenix.db import models
6
+ from phoenix.server.types import DbSessionFactory
7
+
8
+ DatasetID: TypeAlias = int
9
+ Key: TypeAlias = DatasetID
10
+ Result: TypeAlias = list[models.DatasetSplit]
11
+
12
+
13
+ class DatasetDatasetSplitsDataLoader(DataLoader[Key, Result]):
14
+ def __init__(self, db: DbSessionFactory) -> None:
15
+ super().__init__(
16
+ load_fn=self._load_fn,
17
+ )
18
+ self._db = db
19
+
20
+ async def _load_fn(self, keys: list[Key]) -> list[Result]:
21
+ dataset_ids = keys
22
+ async with self._db() as session:
23
+ splits: dict[DatasetID, dict[int, models.DatasetSplit]] = {
24
+ dataset_id: {} for dataset_id in dataset_ids
25
+ }
26
+
27
+ async for dataset_id, split in await session.stream(
28
+ select(models.DatasetExample.dataset_id, models.DatasetSplit)
29
+ .select_from(models.DatasetSplit)
30
+ .join(
31
+ models.DatasetSplitDatasetExample,
32
+ onclause=(
33
+ models.DatasetSplit.id == models.DatasetSplitDatasetExample.dataset_split_id
34
+ ),
35
+ )
36
+ .join(
37
+ models.DatasetExample,
38
+ onclause=(
39
+ models.DatasetSplitDatasetExample.dataset_example_id
40
+ == models.DatasetExample.id
41
+ ),
42
+ )
43
+ .where(models.DatasetExample.dataset_id.in_(dataset_ids))
44
+ ):
45
+ # Use dict to deduplicate splits by split.id
46
+ if dataset_id in splits:
47
+ splits[dataset_id][split.id] = split
48
+
49
+ return [
50
+ sorted(splits.get(dataset_id, {}).values(), key=lambda x: x.name)
51
+ for dataset_id in keys
52
+ ]
@@ -1,8 +1,16 @@
1
+ from dataclasses import dataclass
1
2
  from enum import Enum, auto
3
+ from typing import Any, Optional
2
4
 
3
5
  import strawberry
6
+ from sqlalchemy import and_, desc, func, nulls_last, select
7
+ from sqlalchemy.orm import InstrumentedAttribute
8
+ from sqlalchemy.sql.expression import Select
9
+ from strawberry import UNSET
4
10
  from typing_extensions import assert_never
5
11
 
12
+ from phoenix.db import models
13
+ from phoenix.db.helpers import truncate_name
6
14
  from phoenix.server.api.types.pagination import CursorSortColumnDataType
7
15
  from phoenix.server.api.types.SortDir import SortDir
8
16
 
@@ -15,6 +23,29 @@ class ProjectSessionColumn(Enum):
15
23
  numTraces = auto()
16
24
  costTotal = auto()
17
25
 
26
+ @property
27
+ def column_name(self) -> str:
28
+ return truncate_name(f"{self.name}_project_session_sort_column")
29
+
30
+ def as_orm_expression(self, joined_table: Optional[Any] = None) -> Any:
31
+ expr: Any
32
+ if self is ProjectSessionColumn.startTime:
33
+ expr = models.ProjectSession.start_time
34
+ elif self is ProjectSessionColumn.endTime:
35
+ expr = models.ProjectSession.end_time
36
+ elif self is ProjectSessionColumn.tokenCountTotal:
37
+ assert joined_table is not None
38
+ expr = joined_table.c.key
39
+ elif self is ProjectSessionColumn.numTraces:
40
+ assert joined_table is not None
41
+ expr = joined_table.c.key
42
+ elif self is ProjectSessionColumn.costTotal:
43
+ assert joined_table is not None
44
+ expr = joined_table.c.key
45
+ else:
46
+ assert_never(self)
47
+ return expr.label(self.column_name)
48
+
18
49
  @property
19
50
  def data_type(self) -> CursorSortColumnDataType:
20
51
  if self is ProjectSessionColumn.tokenCountTotal or self is ProjectSessionColumn.numTraces:
@@ -25,8 +56,134 @@ class ProjectSessionColumn(Enum):
25
56
  return CursorSortColumnDataType.FLOAT
26
57
  assert_never(self)
27
58
 
59
+ def join_tables(self, stmt: Select[Any]) -> tuple[Select[Any], Any]:
60
+ """
61
+ If needed, joins tables required for the sort column.
62
+ """
63
+ if self is ProjectSessionColumn.tokenCountTotal:
64
+ sort_subq = (
65
+ select(
66
+ models.Trace.project_session_rowid.label("id"),
67
+ func.sum(models.Span.cumulative_llm_token_count_total).label("key"),
68
+ )
69
+ .join_from(models.Trace, models.Span)
70
+ .where(models.Span.parent_id.is_(None))
71
+ .group_by(models.Trace.project_session_rowid)
72
+ ).subquery()
73
+ stmt = stmt.join(sort_subq, models.ProjectSession.id == sort_subq.c.id)
74
+ return stmt, sort_subq
75
+ if self is ProjectSessionColumn.numTraces:
76
+ sort_subq = (
77
+ select(
78
+ models.Trace.project_session_rowid.label("id"),
79
+ func.count(models.Trace.id).label("key"),
80
+ ).group_by(models.Trace.project_session_rowid)
81
+ ).subquery()
82
+ stmt = stmt.join(sort_subq, models.ProjectSession.id == sort_subq.c.id)
83
+ return stmt, sort_subq
84
+ if self is ProjectSessionColumn.costTotal:
85
+ sort_subq = (
86
+ select(
87
+ models.Trace.project_session_rowid.label("id"),
88
+ func.sum(models.SpanCost.total_cost).label("key"),
89
+ )
90
+ .join_from(
91
+ models.Trace,
92
+ models.SpanCost,
93
+ models.Trace.id == models.SpanCost.trace_rowid,
94
+ )
95
+ .group_by(models.Trace.project_session_rowid)
96
+ ).subquery()
97
+ stmt = stmt.join(sort_subq, models.ProjectSession.id == sort_subq.c.id)
98
+ return stmt, sort_subq
99
+ return stmt, None
100
+
101
+
102
+ @strawberry.enum
103
+ class ProjectSessionAnnoAttr(Enum):
104
+ score = "score"
105
+ label = "label"
106
+
107
+ @property
108
+ def column_name(self) -> str:
109
+ return f"{self.value}_anno_sort_column"
110
+
111
+ @property
112
+ def orm_expression(self) -> Any:
113
+ expr: InstrumentedAttribute[Any]
114
+ if self is ProjectSessionAnnoAttr.score:
115
+ expr = models.ProjectSessionAnnotation.score
116
+ elif self is ProjectSessionAnnoAttr.label:
117
+ expr = models.ProjectSessionAnnotation.label
118
+ else:
119
+ assert_never(self)
120
+ return expr.label(self.column_name)
121
+
122
+ @property
123
+ def data_type(self) -> CursorSortColumnDataType:
124
+ if self is ProjectSessionAnnoAttr.label:
125
+ return CursorSortColumnDataType.STRING
126
+ if self is ProjectSessionAnnoAttr.score:
127
+ return CursorSortColumnDataType.FLOAT
128
+ assert_never(self)
129
+
130
+
131
+ @strawberry.input
132
+ class ProjectSessionAnnoResultKey:
133
+ name: str
134
+ attr: ProjectSessionAnnoAttr
135
+
136
+
137
+ @dataclass(frozen=True)
138
+ class ProjectSessionSortConfig:
139
+ stmt: Select[Any]
140
+ orm_expression: Any
141
+ dir: SortDir
142
+ column_name: str
143
+ column_data_type: CursorSortColumnDataType
144
+
28
145
 
29
146
  @strawberry.input(description="The sort key and direction for ProjectSession connections.")
30
147
  class ProjectSessionSort:
31
- col: ProjectSessionColumn
148
+ col: Optional[ProjectSessionColumn] = UNSET
149
+ anno_result_key: Optional[ProjectSessionAnnoResultKey] = UNSET
32
150
  dir: SortDir
151
+
152
+ def update_orm_expr(self, stmt: Select[Any]) -> ProjectSessionSortConfig:
153
+ if (col := self.col) and not self.anno_result_key:
154
+ stmt, joined_table = col.join_tables(stmt)
155
+ expr = col.as_orm_expression(joined_table)
156
+ stmt = stmt.add_columns(expr)
157
+ if self.dir == SortDir.desc:
158
+ expr = desc(expr)
159
+ return ProjectSessionSortConfig(
160
+ stmt=stmt.order_by(nulls_last(expr)),
161
+ orm_expression=col.as_orm_expression(joined_table),
162
+ dir=self.dir,
163
+ column_name=col.column_name,
164
+ column_data_type=col.data_type,
165
+ )
166
+ if (anno_result_key := self.anno_result_key) and not col:
167
+ anno_name = anno_result_key.name
168
+ anno_attr = anno_result_key.attr
169
+ expr = anno_result_key.attr.orm_expression
170
+ stmt = stmt.add_columns(expr)
171
+ if self.dir == SortDir.desc:
172
+ expr = desc(expr)
173
+ stmt = stmt.join(
174
+ models.ProjectSessionAnnotation,
175
+ onclause=and_(
176
+ models.ProjectSessionAnnotation.project_session_id == models.ProjectSession.id,
177
+ models.ProjectSessionAnnotation.name == anno_name,
178
+ ),
179
+ ).order_by(nulls_last(expr))
180
+ return ProjectSessionSortConfig(
181
+ stmt=stmt,
182
+ orm_expression=anno_result_key.attr.orm_expression,
183
+ dir=self.dir,
184
+ column_name=anno_attr.column_name,
185
+ column_data_type=anno_attr.data_type,
186
+ )
187
+ raise ValueError(
188
+ "Exactly one of `col` or `annoResultKey` must be specified on `ProjectSessionSort`."
189
+ )
@@ -11,6 +11,7 @@ from typing_extensions import assert_never
11
11
 
12
12
  import phoenix.trace.v1 as pb
13
13
  from phoenix.db import models
14
+ from phoenix.db.helpers import truncate_name
14
15
  from phoenix.server.api.types.pagination import CursorSortColumnDataType
15
16
  from phoenix.server.api.types.SortDir import SortDir
16
17
  from phoenix.trace.schemas import SpanID
@@ -32,7 +33,7 @@ class SpanColumn(Enum):
32
33
 
33
34
  @property
34
35
  def column_name(self) -> str:
35
- return f"{self.name}_span_sort_column"
36
+ return truncate_name(f"{self.name}_span_sort_column")
36
37
 
37
38
  def as_orm_expression(self, joined_table: Optional[Any] = None) -> Any:
38
39
  expr: Any
@@ -7,3 +7,4 @@ import strawberry
7
7
  class UserRoleInput(Enum):
8
8
  ADMIN = "ADMIN"
9
9
  MEMBER = "MEMBER"
10
+ VIEWER = "VIEWER"