arize-phoenix 11.8.0__py3-none-any.whl → 11.10.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 (30) hide show
  1. {arize_phoenix-11.8.0.dist-info → arize_phoenix-11.10.0.dist-info}/METADATA +1 -1
  2. {arize_phoenix-11.8.0.dist-info → arize_phoenix-11.10.0.dist-info}/RECORD +26 -25
  3. phoenix/db/insertion/span.py +12 -10
  4. phoenix/db/insertion/types.py +9 -2
  5. phoenix/server/api/input_types/CreateProjectInput.py +27 -0
  6. phoenix/server/api/mutations/project_mutations.py +37 -1
  7. phoenix/server/api/mutations/trace_mutations.py +45 -1
  8. phoenix/server/api/types/Project.py +589 -11
  9. phoenix/server/cost_tracking/model_cost_manifest.json +85 -0
  10. phoenix/server/dml_event.py +4 -0
  11. phoenix/server/static/.vite/manifest.json +41 -41
  12. phoenix/server/static/assets/{components-5M9nebi4.js → components-XAeml0-1.js} +400 -326
  13. phoenix/server/static/assets/{index-OU2WTnGN.js → index-D7EtHUpz.js} +37 -9
  14. phoenix/server/static/assets/{pages-DF8rqxJ4.js → pages-CPfaxiKa.js} +642 -437
  15. phoenix/server/static/assets/vendor-CqDb5u4o.css +1 -0
  16. phoenix/server/static/assets/vendor-DhvamIr8.js +939 -0
  17. phoenix/server/static/assets/vendor-arizeai-4fVwwnrI.js +168 -0
  18. phoenix/server/static/assets/{vendor-codemirror-vlcH1_iR.js → vendor-codemirror-DRfFHb57.js} +1 -1
  19. phoenix/server/static/assets/vendor-recharts-w6bSawXG.js +37 -0
  20. phoenix/server/static/assets/{vendor-shiki-BsknB7bv.js → vendor-shiki-CplrhwOk.js} +1 -1
  21. phoenix/server/templates/index.html +3 -4
  22. phoenix/version.py +1 -1
  23. phoenix/server/static/assets/vendor-Bl7CyFDw.js +0 -911
  24. phoenix/server/static/assets/vendor-WIZid84E.css +0 -1
  25. phoenix/server/static/assets/vendor-arizeai-B_viEUUA.js +0 -180
  26. phoenix/server/static/assets/vendor-recharts-C9cQu72o.js +0 -59
  27. {arize_phoenix-11.8.0.dist-info → arize_phoenix-11.10.0.dist-info}/WHEEL +0 -0
  28. {arize_phoenix-11.8.0.dist-info → arize_phoenix-11.10.0.dist-info}/entry_points.txt +0 -0
  29. {arize_phoenix-11.8.0.dist-info → arize_phoenix-11.10.0.dist-info}/licenses/IP_NOTICE +0 -0
  30. {arize_phoenix-11.8.0.dist-info → arize_phoenix-11.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 11.8.0
3
+ Version: 11.10.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
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
6
6
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
7
  phoenix/services.py,sha256=ngkyKGVatX3cO2WJdo2hKdaVKP-xJCMvqthvga6kJss,5196
8
8
  phoenix/settings.py,sha256=2kHfT3BNOVd4dAO1bq-syEQbHSG8oX2-7NhOwK2QREk,896
9
- phoenix/version.py,sha256=i-ilTWt69mdcN4GqSDKAmTIOlguLxG2mm9Xhzz2U_aw,23
9
+ phoenix/version.py,sha256=QWduDFvGZEp2yqC4pdaQmCm9ifKoDwiu-l0lM7_65A0,24
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
@@ -30,10 +30,10 @@ phoenix/db/insertion/dataset.py,sha256=KeUtfSnznmkDDlGs6KM5URduZtIo8I951tybamwoL
30
30
  phoenix/db/insertion/document_annotation.py,sha256=46IHWgILlIIoCkzgEtZIubqfpgF9KVA8ETWeblcpff0,6544
31
31
  phoenix/db/insertion/evaluation.py,sha256=XIlDQMx9FFu_hO1TEao8_ScgKETw61AoeGezsmngXrY,6876
32
32
  phoenix/db/insertion/helpers.py,sha256=wA4f_B8DI1pfNvX7R5luG1MklwX6rtCrvv_SOcjtJGo,4106
33
- phoenix/db/insertion/span.py,sha256=UTPwWx-rSxIjRjr1x-p-RkECDmsHfNv0iSXLEooELMM,8189
33
+ phoenix/db/insertion/span.py,sha256=UB4UR8QlkJdVzbJ7_-S6FXIHYjyKZSOEVzCOvwGw7cY,8414
34
34
  phoenix/db/insertion/span_annotation.py,sha256=7m0kaOkdHhLTqs_E9Kt8BeCiHUpaU3mspm5ZdMz3lio,5728
35
35
  phoenix/db/insertion/trace_annotation.py,sha256=Qijh7eROXLjV6OLIuKwsrc2OB9A7JnefzP4eZxlPRlc,5768
36
- phoenix/db/insertion/types.py,sha256=0p1IQj4WlhNAWonuCnNzWaV6G6xTvAFXRattUGw_zrk,8378
36
+ phoenix/db/insertion/types.py,sha256=T9WjPxqt7N3AuZ9WA53WT85jmFmPaHcJ98wdPxByISo,8760
37
37
  phoenix/db/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  phoenix/db/migrations/env.py,sha256=tFO3ceuCx9Es5_2w_BXclaQMmNQKNX21b1UEV5mYdeo,3387
39
39
  phoenix/db/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
@@ -94,7 +94,7 @@ phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
94
  phoenix/server/app.py,sha256=tB00x9r0PcCLYkvOtTQ7LqdSyw7jqy8OY5e7UVYl5UE,46951
95
95
  phoenix/server/authorization.py,sha256=OxROn7ibpKtCTrcgDkzWuNxVaQcSQ8MAx7zbjZiliK0,3201
96
96
  phoenix/server/bearer_auth.py,sha256=f4v4W94KyTdGGCPsK1tXOe0vouPuvanAEa03XSdCvPE,6650
97
- phoenix/server/dml_event.py,sha256=MjJmVEKytq75chBOSyvYDusUnEbg1pHpIjR3pZkUaJA,2838
97
+ phoenix/server/dml_event.py,sha256=8UciN7W8X_IqQfAnAeAh68BezNmfxSxuTeD6IUerTW8,2911
98
98
  phoenix/server/dml_event_handler.py,sha256=gkDIONyTz9sLbSA6qOZCigiO5val-fvVcLzDrWNcVcg,8306
99
99
  phoenix/server/grpc_server.py,sha256=ahHC394gFZYM3h4FmjQxZwL-a4x3mWmV2EdXYFlNEC8,4676
100
100
  phoenix/server/jwt_store.py,sha256=B6uVildN_dQDTG_-aHHvuVSI7wIVK1yvED-_y6se2GU,16905
@@ -193,6 +193,7 @@ phoenix/server/api/input_types/ClearProjectInput.py,sha256=cpPFRyQ3ffy2dLbCZgYpw
193
193
  phoenix/server/api/input_types/ClusterInput.py,sha256=AfhuYYHlYgdMO6Ap8cLXqAp70S0Wutx-RTzZYetN62A,173
194
194
  phoenix/server/api/input_types/Coordinates.py,sha256=meTwbIjwTfqx5DGD2DBlH9wQzdQVNM5a8x9dp1FfIgA,173
195
195
  phoenix/server/api/input_types/CreateDatasetInput.py,sha256=Q3MwouIx9jTQBRWDju75iMQXEGJCrL4aD4ESQp771nc,248
196
+ phoenix/server/api/input_types/CreateProjectInput.py,sha256=ySfMzilUl5H0WAxcbn1rN-AlElbQGOgKT2-oY4JtnfY,866
196
197
  phoenix/server/api/input_types/CreateSpanAnnotationInput.py,sha256=BtPB8udqnpK7kQxPpryxoO4D4yoN1E4qYF2VZxqw2LQ,706
197
198
  phoenix/server/api/input_types/CreateTraceAnnotationInput.py,sha256=GBzOwRw_GNQq3RwS5kDp32j55VI1czOmvEmRESqCsRQ,625
198
199
  phoenix/server/api/input_types/DataQualityMetricInput.py,sha256=WPWRlqSejOnxlLqsbEwPCDgz8ocsyGSb-9SptdCjZEc,1361
@@ -235,14 +236,14 @@ phoenix/server/api/mutations/dataset_mutations.py,sha256=KRlF-Ag3twqaBpLR_6WYxf5
235
236
  phoenix/server/api/mutations/experiment_mutations.py,sha256=p3CoLAa8nFPa3D759Y2A7De_PVJNGOL98mA3HoZBrRQ,3188
236
237
  phoenix/server/api/mutations/export_events_mutations.py,sha256=xoDnVWC7eA_8wNQP0-oyiHojyUZ0EhVVSrsAnztetC0,3993
237
238
  phoenix/server/api/mutations/model_mutations.py,sha256=eh-QIKww3EDrDewS3NTWTqnE2bwLJJ5WgRFvSPRksZg,7199
238
- phoenix/server/api/mutations/project_mutations.py,sha256=mhXw1ChBtdHCF3GOls66hHJmr5ohkICugp82o09e-sc,2926
239
+ phoenix/server/api/mutations/project_mutations.py,sha256=PQCwODI0VXk9Rllxdar4bNEyaYb1rJiMHXTqol-cFYY,4569
239
240
  phoenix/server/api/mutations/project_trace_retention_policy_mutations.py,sha256=AqBe8TBxlXdIL56Afs4FIBqkI0bEgf-v9bHlbc-O6VI,9839
240
241
  phoenix/server/api/mutations/prompt_label_mutations.py,sha256=uCiVcULtmgaNaav4M08ipPYM68sZv1MVLrCgvW-Xyn8,7317
241
242
  phoenix/server/api/mutations/prompt_mutations.py,sha256=Yg-6L2PiKUZfFyNarptu3OdE0uA2_Nyl3VrLVP8FJ9Y,12114
242
243
  phoenix/server/api/mutations/prompt_version_tag_mutations.py,sha256=t77osYb5he2Am4UeNis7pzY9MnaA9PNEQhsQelRH8k8,5767
243
244
  phoenix/server/api/mutations/span_annotations_mutations.py,sha256=LQPcODp7-ZobXspjmtLaamyQa8UkTONC_va-ST9r-k8,15015
244
245
  phoenix/server/api/mutations/trace_annotations_mutations.py,sha256=PLNNzSlk3fyJHkAVaMGR8pbWB63nOos-cStUWbTi7f8,11995
245
- phoenix/server/api/mutations/trace_mutations.py,sha256=D5h2HYdlTo6yYZNq-O-PjaS9GeiZHxxVaOxDdh7fwjw,2957
246
+ phoenix/server/api/mutations/trace_mutations.py,sha256=AvtQAfqNWBQpJOZm4e0DZFimhVJ6HQHtSSZtezRadCo,4698
246
247
  phoenix/server/api/mutations/user_mutations.py,sha256=pNQ7nyOnqBsm5pAQALdvsEaGM889JQTKg0kBv_-YyYs,15393
247
248
  phoenix/server/api/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
248
249
  phoenix/server/api/openapi/main.py,sha256=yKdzJYI4cxy_1mFcK4_7YObIcuRviBIfwNjB23RG14k,461
@@ -319,7 +320,7 @@ phoenix/server/api/types/ModelInterface.py,sha256=Qe7H23wDb_Q2-HmeY2t0R5Jsn4aAfY
319
320
  phoenix/server/api/types/NumericRange.py,sha256=afEjgF97Go_OvmjMggbPBt-zGM8IONewAyEiKEHRds0,192
320
321
  phoenix/server/api/types/PerformanceMetric.py,sha256=KFkmJDqP43eDUtARQOUqR7NYcxvL6Vh2uisHWU6H3ko,387
321
322
  phoenix/server/api/types/PlaygroundModel.py,sha256=IqJFxsAAJMRyaFI9ryI3GQrpFOJ5Llf6kIutEO-tFvM,321
322
- phoenix/server/api/types/Project.py,sha256=byVCH6gG1o0G5OZwa4M_MA76HmfpPZQAugFcoTr8SfQ,41592
323
+ phoenix/server/api/types/Project.py,sha256=FE93mSrWKv1rcCPECfp1hsCen2012SPp-1pCEVuq5ic,64039
323
324
  phoenix/server/api/types/ProjectSession.py,sha256=uwqTsDTfSGz13AvP-cwS_mJR5JZ1lHqu10ungbl7g5s,6245
324
325
  phoenix/server/api/types/ProjectTraceRetentionPolicy.py,sha256=tYy2kgalPDyuaYZr0VUHjH0YpXaiF_QOzg5yfaV_c7c,3782
325
326
  phoenix/server/api/types/Prompt.py,sha256=ccP4eq1e38xbF0afclGWLOuDpBVpNbJ3AOSRClF8yFQ,4955
@@ -359,7 +360,7 @@ phoenix/server/cost_tracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
359
360
  phoenix/server/cost_tracking/cost_details_calculator.py,sha256=Tt0YcuLhgPuXKWJemWVmYQfG0xQUvH4VziIj6KcDnoA,8945
360
361
  phoenix/server/cost_tracking/cost_model_lookup.py,sha256=jhtVdnQBzrTUHeOGPWgOebk-Io5hpJ1vAgWOu8ojeJ4,6801
361
362
  phoenix/server/cost_tracking/helpers.py,sha256=Pk6ECjnYreTxrldtRwxnwFcxIPVsvDq_yAwDA_spkOc,2122
362
- phoenix/server/cost_tracking/model_cost_manifest.json,sha256=sMXOjssVwcJkmdMapA5-eYjXIboUu8FDosuXGL3q1Cw,53862
363
+ phoenix/server/cost_tracking/model_cost_manifest.json,sha256=aIprOWjHWUz0nrkDHII5dDybGi5prD-_xa3IGC-e838,55889
363
364
  phoenix/server/cost_tracking/regex_specificity.py,sha256=9kqWuQ68C-hlwW25hr7BhFlRt5y2Nnpy0Ax3n9UN6Xk,11622
364
365
  phoenix/server/cost_tracking/token_cost_calculator.py,sha256=2JEZnvusx2-xbhp8krp9EarjWuyGH2KO4e-ZwJX-K0s,1598
365
366
  phoenix/server/daemons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -386,19 +387,19 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
386
387
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
387
388
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
388
389
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
389
- phoenix/server/static/.vite/manifest.json,sha256=TyIBjaXaDHUOqmU0l4oXKq2CPJP8mvLfjzljq2lvLSI,2165
390
- phoenix/server/static/assets/components-5M9nebi4.js,sha256=q_bd0ZLoJNT4GRB6t3HlPFge6BE7_Zm0Ba1pPMszXho,617280
391
- phoenix/server/static/assets/index-OU2WTnGN.js,sha256=Ffe2oGJzh4KIQBhqrGMSJmLB0IDtzQZqTzEHCfJ1n00,61725
392
- phoenix/server/static/assets/pages-DF8rqxJ4.js,sha256=2SsqPLQAtFywkipQhDy-Vvp6Xyud-DDhHGb-85JYzSQ,1150693
393
- phoenix/server/static/assets/vendor-Bl7CyFDw.js,sha256=RX9lDZywB-FfD-MNfY5KYxVVq5laI2AcmH9rhVuCsnE,2739824
394
- phoenix/server/static/assets/vendor-WIZid84E.css,sha256=spZD2r7XL5GfLO13ln-IuXfnjAref8l6g_n_AvxxOlI,5517
395
- phoenix/server/static/assets/vendor-arizeai-B_viEUUA.js,sha256=ir0WQ2dSxIEhK6wDi7A1FKPaG7Bmgze_V5S7RfBxFBM,167428
396
- phoenix/server/static/assets/vendor-codemirror-vlcH1_iR.js,sha256=BFxUiyr9u03kekfUjR4JIVR1D8-VnZjUo8bjmAigUtw,781264
397
- phoenix/server/static/assets/vendor-recharts-C9cQu72o.js,sha256=fm3quX1HWJ9sbIZhDrHsnZZpSg0LhsQtMV21NB5MPTM,282150
398
- phoenix/server/static/assets/vendor-shiki-BsknB7bv.js,sha256=5X-FxGYbuoFMIfOtX9LD9Qju-2oT1smMbgYyoHprI7k,8980312
390
+ phoenix/server/static/.vite/manifest.json,sha256=67Jr1Pbvt4QUZP4O98Fe_9tPLJvVHSKqSJeYcfC2oVk,2165
391
+ phoenix/server/static/assets/components-XAeml0-1.js,sha256=aCeHz5UUtnMLqWDeVRMmHJnjMHgwEDjpdRoz_tJ063s,620501
392
+ phoenix/server/static/assets/index-D7EtHUpz.js,sha256=FBp-_XLUtdcJ3wLAdu0peRKAPTkU2Ceu_U2Fu-QRfDg,62601
393
+ phoenix/server/static/assets/pages-CPfaxiKa.js,sha256=EyoqjFXTFOgpww-GDBYnH7KfsLfV84OI06WYG0xmUjo,1190498
394
+ phoenix/server/static/assets/vendor-CqDb5u4o.css,sha256=zIyFiNJKxMaQk8AvtLgt1rR01oO10d1MFndSDKH9Clw,5517
395
+ phoenix/server/static/assets/vendor-DhvamIr8.js,sha256=hZdQcaVySUPWh4GXRhuL-PhUy2K4sJLs6gYxde6qB_I,2748936
396
+ phoenix/server/static/assets/vendor-arizeai-4fVwwnrI.js,sha256=8eBZfGf2fjjNoWDW31mHXdxkqSlWItGj7eHhbnH92Qk,151750
397
+ phoenix/server/static/assets/vendor-codemirror-DRfFHb57.js,sha256=v-q8mq6f-EbjtvgzLTQYF-SNKX4R6LOGJe5ucOMqx1w,781264
398
+ phoenix/server/static/assets/vendor-recharts-w6bSawXG.js,sha256=uTuxE0vslP7_y-F1dOU5K2nXke7qe8JMdE2SnRGCVKM,231651
399
+ phoenix/server/static/assets/vendor-shiki-CplrhwOk.js,sha256=ISu7sYmhh_FDTmnBN-icbipm6fa2InqOeQTo2JFr3LI,8980312
399
400
  phoenix/server/static/assets/vendor-three-C5WAXd5r.js,sha256=ELkg06u70N7h8oFmvqdoHyPuUf9VgGEWeT4LKFx4VWo,620975
400
401
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
401
- phoenix/server/templates/index.html,sha256=rTdJZOlbZmm1dMCrHWikAwcecZDxduPU5zCFd2h2cbs,6819
402
+ phoenix/server/templates/index.html,sha256=3VMDmbxYwo3OoqiQyFojU6JaMLKr5k8rITacYS7HTbs,6922
402
403
  phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
403
404
  phoenix/session/client.py,sha256=uw5WlCuFcN_eEj7Ko2bhJVcaihEIp7Evy50KnL6Sq-k,35602
404
405
  phoenix/session/data_extractor.py,sha256=Y0RzYFaNy9fQj8PEIeQ76TBZ90_E1FW7bXu3K5x0EZY,2782
@@ -436,9 +437,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
436
437
  phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
437
438
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
438
439
  phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
439
- arize_phoenix-11.8.0.dist-info/METADATA,sha256=QEqV4jJ6yjmlUIiyR2119BCyHw-Hi-pH6wm6rUc5c8k,30850
440
- arize_phoenix-11.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
441
- arize_phoenix-11.8.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
442
- arize_phoenix-11.8.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
443
- arize_phoenix-11.8.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
444
- arize_phoenix-11.8.0.dist-info/RECORD,,
440
+ arize_phoenix-11.10.0.dist-info/METADATA,sha256=-AwyriOi2Hypd_vYo7mrHEKmXIoypvFLTTmwn_MkdKA,30851
441
+ arize_phoenix-11.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
442
+ arize_phoenix-11.10.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
443
+ arize_phoenix-11.10.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
444
+ arize_phoenix-11.10.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
445
+ arize_phoenix-11.10.0.dist-info/RECORD,,
@@ -28,15 +28,6 @@ async def insert_span(
28
28
  project_name: str,
29
29
  ) -> Optional[SpanInsertionEvent]:
30
30
  dialect = SupportedSQLDialect(session.bind.dialect.name)
31
- if (
32
- project_rowid := await session.scalar(
33
- select(models.Project.id).filter_by(name=project_name)
34
- )
35
- ) is None:
36
- project_rowid = await session.scalar(
37
- insert(models.Project).values(name=project_name).returning(models.Project.id)
38
- )
39
- assert project_rowid is not None
40
31
 
41
32
  trace_id = span.context.trace_id
42
33
  trace: models.Trace = await session.scalar(
@@ -44,16 +35,27 @@ async def insert_span(
44
35
  ) or models.Trace(trace_id=trace_id)
45
36
 
46
37
  if trace.id is not None:
38
+ # We use the existing project_rowid on the trace because we allow users to transfer traces
39
+ # between projects, so the project_name parameter is ignored for existing traces.
40
+ project_rowid = trace.project_rowid
47
41
  # Trace record may need to be updated.
48
42
  if trace.end_time < span.end_time:
49
43
  trace.end_time = span.end_time
50
- trace.project_rowid = project_rowid
51
44
  if span.start_time < trace.start_time:
52
45
  trace.start_time = span.start_time
53
46
  else:
54
47
  # Trace record needs to be persisted for the first time.
55
48
  trace.start_time = span.start_time
56
49
  trace.end_time = span.end_time
50
+ if (
51
+ project_rowid := await session.scalar(
52
+ select(models.Project.id).filter_by(name=project_name)
53
+ )
54
+ ) is None:
55
+ project_rowid = await session.scalar(
56
+ insert(models.Project).values(name=project_name).returning(models.Project.id)
57
+ )
58
+ assert project_rowid is not None
57
59
  trace.project_rowid = project_rowid
58
60
  session.add(trace)
59
61
 
@@ -94,7 +94,10 @@ class QueueInserter(ABC, Generic[_PrecursorT, _InsertableT, _RowT, _DmlEventT]):
94
94
  async def insert(self) -> Optional[list[_DmlEventT]]:
95
95
  if not self._queue:
96
96
  return None
97
- self._queue, parcels = [], self._queue
97
+ parcels = self._queue.copy()
98
+ # IMPORTANT: Use .clear() instead of reassignment, i.e. self._queue = [], to
99
+ # avoid potential race conditions when appending postponed items to the queue.
100
+ self._queue.clear()
98
101
  events: list[_DmlEventT] = []
99
102
  async with self._db() as session:
100
103
  to_insert, to_postpone, _ = await self._partition(session, *parcels)
@@ -104,9 +107,13 @@ class QueueInserter(ABC, Generic[_PrecursorT, _InsertableT, _RowT, _DmlEventT]):
104
107
  to_postpone.extend(to_retry)
105
108
  if to_postpone:
106
109
  loop = asyncio.get_running_loop()
107
- loop.call_later(self._retry_delay_sec, self._queue.extend, to_postpone)
110
+ loop.call_later(self._retry_delay_sec, self._add_postponed_to_queue, to_postpone)
108
111
  return events
109
112
 
113
+ def _add_postponed_to_queue(self, items: list[Postponed[_PrecursorT]]) -> None:
114
+ """Add postponed items back to the queue for retry."""
115
+ self._queue.extend(items)
116
+
110
117
  def _insert_on_conflict(self, *records: Mapping[str, Any]) -> Insert:
111
118
  return insert_on_conflict(
112
119
  *records,
@@ -0,0 +1,27 @@
1
+ import re
2
+ from typing import Optional
3
+
4
+ import strawberry
5
+ from strawberry import UNSET
6
+
7
+ from phoenix.server.api.exceptions import BadRequest
8
+
9
+
10
+ @strawberry.input
11
+ class CreateProjectInput:
12
+ name: str
13
+ description: Optional[str] = UNSET
14
+ gradient_start_color: Optional[str] = UNSET
15
+ gradient_end_color: Optional[str] = UNSET
16
+
17
+ def __post_init__(self) -> None:
18
+ if not self.name.strip():
19
+ raise BadRequest("Name cannot be empty")
20
+ if self.gradient_start_color and not re.match(
21
+ r"^#([0-9a-fA-F]{6})$", self.gradient_start_color
22
+ ):
23
+ raise BadRequest("Gradient start color must be a valid hex color")
24
+ if self.gradient_end_color and not re.match(
25
+ r"^#([0-9a-fA-F]{6})$", self.gradient_end_color
26
+ ):
27
+ raise BadRequest("Gradient end color must be a valid hex color")
@@ -1,6 +1,8 @@
1
1
  import strawberry
2
2
  from sqlalchemy import delete, select
3
+ from sqlalchemy.exc import IntegrityError as PostgreSQLIntegrityError
3
4
  from sqlalchemy.orm import load_only
5
+ from sqlean.dbapi2 import IntegrityError as SQLiteIntegrityError # type: ignore[import-untyped]
4
6
  from strawberry.relay import GlobalID
5
7
  from strawberry.types import Info
6
8
 
@@ -8,14 +10,48 @@ from phoenix.config import DEFAULT_PROJECT_NAME
8
10
  from phoenix.db import models
9
11
  from phoenix.server.api.auth import IsNotReadOnly
10
12
  from phoenix.server.api.context import Context
13
+ from phoenix.server.api.exceptions import BadRequest, Conflict
11
14
  from phoenix.server.api.input_types.ClearProjectInput import ClearProjectInput
15
+ from phoenix.server.api.input_types.CreateProjectInput import CreateProjectInput
12
16
  from phoenix.server.api.queries import Query
13
17
  from phoenix.server.api.types.node import from_global_id_with_expected_type
14
- from phoenix.server.dml_event import ProjectDeleteEvent, SpanDeleteEvent
18
+ from phoenix.server.api.types.Project import Project, to_gql_project
19
+ from phoenix.server.dml_event import ProjectDeleteEvent, ProjectInsertEvent, SpanDeleteEvent
20
+
21
+
22
+ @strawberry.type
23
+ class ProjectMutationPayload:
24
+ project: Project
25
+ query: Query
15
26
 
16
27
 
17
28
  @strawberry.type
18
29
  class ProjectMutationMixin:
30
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
31
+ async def create_project(
32
+ self,
33
+ info: Info[Context, None],
34
+ input: CreateProjectInput,
35
+ ) -> ProjectMutationPayload:
36
+ if not (name := input.name.strip()):
37
+ raise BadRequest("Name cannot be empty")
38
+ description = (input.description or "").strip() or None
39
+ gradient_start_color = (input.gradient_start_color or "").strip() or None
40
+ gradient_end_color = (input.gradient_end_color or "").strip() or None
41
+ project = models.Project(
42
+ name=name,
43
+ description=description,
44
+ gradient_start_color=gradient_start_color,
45
+ gradient_end_color=gradient_end_color,
46
+ )
47
+ try:
48
+ async with info.context.db() as session:
49
+ session.add(project)
50
+ except (PostgreSQLIntegrityError, SQLiteIntegrityError):
51
+ raise Conflict(f"Project with name '{name}' already exists")
52
+ info.context.event_queue.put(ProjectInsertEvent((project.id,)))
53
+ return ProjectMutationPayload(project=to_gql_project(project), query=Query())
54
+
19
55
  @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
20
56
  async def delete_project(self, info: Info[Context, None], id: GlobalID) -> Query:
21
57
  project_id = from_global_id_with_expected_type(global_id=id, expected_type_name="Project")
@@ -1,5 +1,5 @@
1
1
  import strawberry
2
- from sqlalchemy import and_, delete, not_, select
2
+ from sqlalchemy import and_, delete, not_, select, update
3
3
  from sqlalchemy.orm import load_only
4
4
  from sqlalchemy.sql import literal
5
5
  from strawberry.relay import GlobalID
@@ -72,3 +72,47 @@ class TraceMutationMixin:
72
72
  )
73
73
  info.context.event_queue.put(SpanDeleteEvent(project_ids))
74
74
  return Query()
75
+
76
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
77
+ async def transfer_traces_to_project(
78
+ self,
79
+ info: Info[Context, None],
80
+ trace_ids: list[GlobalID],
81
+ project_id: GlobalID,
82
+ ) -> Query:
83
+ if not trace_ids:
84
+ raise BadRequest("Must provide at least one trace ID to transfer")
85
+ trace_ids = list(set(trace_ids))
86
+ try:
87
+ trace_rowids = [
88
+ from_global_id_with_expected_type(global_id=id, expected_type_name="Trace")
89
+ for id in trace_ids
90
+ ]
91
+ dest_project_rowid = from_global_id_with_expected_type(
92
+ global_id=project_id, expected_type_name="Project"
93
+ )
94
+ except ValueError as error:
95
+ raise BadRequest(str(error))
96
+
97
+ async with info.context.db() as session:
98
+ dest_project = await session.get(models.Project, dest_project_rowid)
99
+ if dest_project is None:
100
+ raise BadRequest("Destination project does not exist")
101
+
102
+ traces = (
103
+ await session.scalars(select(models.Trace).where(models.Trace.id.in_(trace_rowids)))
104
+ ).all()
105
+ if len(traces) < len(trace_rowids):
106
+ raise BadRequest("Invalid trace IDs provided")
107
+
108
+ source_project_ids = set(trace.project_rowid for trace in traces)
109
+ if len(source_project_ids) > 1:
110
+ raise BadRequest("Cannot transfer traces from multiple projects")
111
+
112
+ await session.execute(
113
+ update(models.Trace)
114
+ .where(models.Trace.id.in_(trace_rowids))
115
+ .values(project_rowid=dest_project_rowid)
116
+ )
117
+
118
+ return Query()