arize-phoenix 4.4.4rc4__py3-none-any.whl → 4.4.4rc6__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 (52) hide show
  1. {arize_phoenix-4.4.4rc4.dist-info → arize_phoenix-4.4.4rc6.dist-info}/METADATA +12 -6
  2. {arize_phoenix-4.4.4rc4.dist-info → arize_phoenix-4.4.4rc6.dist-info}/RECORD +47 -42
  3. phoenix/config.py +21 -0
  4. phoenix/datetime_utils.py +4 -0
  5. phoenix/db/insertion/dataset.py +19 -16
  6. phoenix/db/insertion/evaluation.py +4 -4
  7. phoenix/db/insertion/helpers.py +4 -12
  8. phoenix/db/insertion/span.py +3 -3
  9. phoenix/db/migrations/versions/10460e46d750_datasets.py +2 -2
  10. phoenix/db/models.py +8 -3
  11. phoenix/experiments/__init__.py +6 -0
  12. phoenix/experiments/evaluators/__init__.py +29 -0
  13. phoenix/experiments/evaluators/base.py +153 -0
  14. phoenix/{datasets → experiments}/evaluators/code_evaluators.py +25 -53
  15. phoenix/{datasets → experiments}/evaluators/llm_evaluators.py +62 -31
  16. phoenix/experiments/evaluators/utils.py +189 -0
  17. phoenix/experiments/functions.py +616 -0
  18. phoenix/{datasets → experiments}/tracing.py +19 -0
  19. phoenix/experiments/types.py +722 -0
  20. phoenix/experiments/utils.py +9 -0
  21. phoenix/server/api/context.py +4 -0
  22. phoenix/server/api/dataloaders/__init__.py +4 -0
  23. phoenix/server/api/dataloaders/average_experiment_run_latency.py +54 -0
  24. phoenix/server/api/dataloaders/experiment_run_counts.py +42 -0
  25. phoenix/server/api/helpers/dataset_helpers.py +8 -7
  26. phoenix/server/api/input_types/ClearProjectInput.py +15 -0
  27. phoenix/server/api/mutations/project_mutations.py +9 -4
  28. phoenix/server/api/routers/v1/__init__.py +1 -1
  29. phoenix/server/api/routers/v1/dataset_examples.py +10 -10
  30. phoenix/server/api/routers/v1/datasets.py +152 -48
  31. phoenix/server/api/routers/v1/evaluations.py +4 -11
  32. phoenix/server/api/routers/v1/experiment_evaluations.py +23 -23
  33. phoenix/server/api/routers/v1/experiment_runs.py +5 -17
  34. phoenix/server/api/routers/v1/experiments.py +5 -5
  35. phoenix/server/api/routers/v1/spans.py +6 -4
  36. phoenix/server/api/types/Experiment.py +12 -0
  37. phoenix/server/api/types/ExperimentRun.py +1 -1
  38. phoenix/server/api/types/ExperimentRunAnnotation.py +1 -1
  39. phoenix/server/app.py +4 -0
  40. phoenix/server/static/index.js +712 -588
  41. phoenix/session/client.py +321 -28
  42. phoenix/trace/fixtures.py +6 -6
  43. phoenix/utilities/json.py +8 -8
  44. phoenix/version.py +1 -1
  45. phoenix/datasets/__init__.py +0 -0
  46. phoenix/datasets/evaluators/__init__.py +0 -18
  47. phoenix/datasets/evaluators/_utils.py +0 -13
  48. phoenix/datasets/experiments.py +0 -485
  49. phoenix/datasets/types.py +0 -212
  50. {arize_phoenix-4.4.4rc4.dist-info → arize_phoenix-4.4.4rc6.dist-info}/WHEEL +0 -0
  51. {arize_phoenix-4.4.4rc4.dist-info → arize_phoenix-4.4.4rc6.dist-info}/licenses/IP_NOTICE +0 -0
  52. {arize_phoenix-4.4.4rc4.dist-info → arize_phoenix-4.4.4rc6.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arize-phoenix
3
- Version: 4.4.4rc4
3
+ Version: 4.4.4rc6
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
@@ -20,7 +20,7 @@ Requires-Python: <3.13,>=3.8
20
20
  Requires-Dist: aioitertools
21
21
  Requires-Dist: aiosqlite
22
22
  Requires-Dist: alembic<2,>=1.3.0
23
- Requires-Dist: arize-phoenix-evals>=0.3.0
23
+ Requires-Dist: arize-phoenix-evals>=0.13.1
24
24
  Requires-Dist: cachetools
25
25
  Requires-Dist: grpcio
26
26
  Requires-Dist: hdbscan>=0.8.33
@@ -31,12 +31,12 @@ Requires-Dist: openinference-instrumentation
31
31
  Requires-Dist: openinference-instrumentation-langchain>=0.1.12
32
32
  Requires-Dist: openinference-instrumentation-llama-index>=1.2.0
33
33
  Requires-Dist: openinference-instrumentation-openai>=0.1.4
34
- Requires-Dist: openinference-semantic-conventions>=0.1.5
34
+ Requires-Dist: openinference-semantic-conventions>=0.1.9
35
35
  Requires-Dist: opentelemetry-exporter-otlp
36
36
  Requires-Dist: opentelemetry-proto>=1.12.0
37
37
  Requires-Dist: opentelemetry-sdk
38
38
  Requires-Dist: opentelemetry-semantic-conventions
39
- Requires-Dist: pandas
39
+ Requires-Dist: pandas>=1.0
40
40
  Requires-Dist: protobuf<6.0,>=3.20
41
41
  Requires-Dist: psutil
42
42
  Requires-Dist: pyarrow
@@ -79,6 +79,7 @@ Requires-Dist: llama-index>=0.10.3; extra == 'dev'
79
79
  Requires-Dist: nbqa; extra == 'dev'
80
80
  Requires-Dist: pandas-stubs==2.0.3.230814; (python_version < '3.9') and extra == 'dev'
81
81
  Requires-Dist: pandas-stubs==2.2.2.240603; (python_version >= '3.9') and extra == 'dev'
82
+ Requires-Dist: pandas>=1.0; extra == 'dev'
82
83
  Requires-Dist: pre-commit; extra == 'dev'
83
84
  Requires-Dist: prometheus-client; extra == 'dev'
84
85
  Requires-Dist: psycopg[binary]; extra == 'dev'
@@ -88,10 +89,15 @@ Requires-Dist: pytest-postgresql; extra == 'dev'
88
89
  Requires-Dist: pytest==8.2.2; extra == 'dev'
89
90
  Requires-Dist: ruff==0.4.9; extra == 'dev'
90
91
  Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.235.0; extra == 'dev'
92
+ Requires-Dist: tabulate; extra == 'dev'
93
+ Requires-Dist: types-tabulate; extra == 'dev'
91
94
  Provides-Extra: evals
92
95
  Provides-Extra: experimental
93
96
  Provides-Extra: llama-index
94
- Requires-Dist: llama-index==0.10.44; extra == 'llama-index'
97
+ Requires-Dist: llama-index-embeddings-openai; extra == 'llama-index'
98
+ Requires-Dist: llama-index-llms-openai; extra == 'llama-index'
99
+ Requires-Dist: llama-index-readers-file; extra == 'llama-index'
100
+ Requires-Dist: llama-index==0.10.51; extra == 'llama-index'
95
101
  Provides-Extra: pg
96
102
  Requires-Dist: asyncpg; extra == 'pg'
97
103
  Description-Content-Type: text/markdown
@@ -127,7 +133,7 @@ Description-Content-Type: text/markdown
127
133
 
128
134
  Phoenix is an open-source AI observability platform designed for experimentation, evaluation, and troubleshooting. It provides:
129
135
 
130
- - **_Tracing_** - Trace your LLM application's runtime using using OpenTelemetry-based instrumentation.
136
+ - **_Tracing_** - Trace your LLM application's runtime using OpenTelemetry-based instrumentation.
131
137
  - **_Evaluation_** - Leverage LLMs to benchmark your application's performance using response and retrieval evals.
132
138
  - **_Inference Analysis_** - Visualize inferences and embeddings using dimensionality reduction and clustering to identify drift and performance degradation.
133
139
 
@@ -1,24 +1,16 @@
1
1
  phoenix/__init__.py,sha256=JMXBf8J0tAa5ycWDIn8QWYgQu6H2vL77RC4lful-YH8,1542
2
- phoenix/config.py,sha256=9xkQBn_Z-tsQct-zq0B80N4Xa2k2jfhivdc_qYCA5G8,7618
3
- phoenix/datetime_utils.py,sha256=oqkxJ5I7ggrCKYTEi8q-akC501calylD26NVOPQQcHw,3305
2
+ phoenix/config.py,sha256=eXciIho_PDh4ZSmq4Gtuo7Qz__yTluDP3_WUwig5OiU,8141
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
6
  phoenix/services.py,sha256=aTxhcOA1pZHB6U-B3TEcp6fqDF5oT0xCUvEUNMZVTUQ,5175
7
7
  phoenix/settings.py,sha256=cO-qgis_S27nHirTobYI9hHPfZH18R--WMmxNdsVUwc,273
8
- phoenix/version.py,sha256=NZ2gYPUT2LKOK3V9-dZJ34v1J27mnLmDtx-pKAXd1W0,25
8
+ phoenix/version.py,sha256=rZ0Z9PgUs79kMn4HpCH3vAEVOqqPCzzD7Xz8N5sa7qI,25
9
9
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
11
11
  phoenix/core/model.py,sha256=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
12
12
  phoenix/core/model_schema.py,sha256=F2dbbVnkDLsPYoyZDv1q03uhvP8LcU1wXp0g-exiWs0,50551
13
13
  phoenix/core/model_schema_adapter.py,sha256=0Tm_Y_gV-WED8fKBCaFXAEFwE3CTEZS1dowqnTZ7x7g,8426
14
- phoenix/datasets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- phoenix/datasets/experiments.py,sha256=MhuhJWJ-bBqZ_aR3FewudEeo6RUrLgm0hmDlGjWVsrU,19314
16
- phoenix/datasets/tracing.py,sha256=Ieb2Uo-9qHpmv65uf1VsFSsWo5Yxj6VHwGS6dxu9NHQ,2248
17
- phoenix/datasets/types.py,sha256=w0KoSP7AdlcFlV3I6qVtvKOOWoK0yiY6_s4CvH0flcs,5753
18
- phoenix/datasets/evaluators/__init__.py,sha256=KSr9fNG4O93swYxNdPj_UihP9Itl_5mj0a492wi_4_0,465
19
- phoenix/datasets/evaluators/_utils.py,sha256=-MaNdoN1hA3FLzLyIDplUUkUtmM56BMIV83Gh-sgAsU,436
20
- phoenix/datasets/evaluators/code_evaluators.py,sha256=fwoKfyHD7_xBaHY8Ax78xcry7PtB8Y1FxIn82guAV5M,4640
21
- phoenix/datasets/evaluators/llm_evaluators.py,sha256=Ghg3bIBtQCdd6LuQ6VdcbkNQKI9ouZXwjlJV5GcdxOg,8675
22
14
  phoenix/db/README.md,sha256=IvKaZyf9ECbGBYYePaRhBveKZwDbxAc-c7BMxJYZh6Q,595
23
15
  phoenix/db/__init__.py,sha256=pDjEFXukHmJBM-1D8RjmXkvLsz85YWNxMQczt81ec3A,118
24
16
  phoenix/db/alembic.ini,sha256=p8DjVqGUs_tTx8oU56JP7qj-rMUebNFizItUSv_hPhs,3763
@@ -26,18 +18,28 @@ phoenix/db/bulk_inserter.py,sha256=zbZGWZFDybKaGLGzpxgLwxAS5sC0_wXcvM0be4kUhh8,1
26
18
  phoenix/db/engines.py,sha256=vLWaZlToMtDI7rJDxSidYkfOoojamxaZxaz8ND3zTus,4770
27
19
  phoenix/db/helpers.py,sha256=L2_jP1iIWpUREhKLYYb4_vf_6v_BiU1E73Z2PczGm6s,1589
28
20
  phoenix/db/migrate.py,sha256=MuhtNWnR24riROvarvKfbRb4_D5xuQi6P760vBUKl1E,2270
29
- phoenix/db/models.py,sha256=zzZHXh1NpS3LyOOFp1BS7aVyrU1Qx3gcBY-H8ouoyjg,20282
21
+ phoenix/db/models.py,sha256=zFtdhVuQFOvquyKsto62aqAVaTRUlq9gxU0j1M1yLdg,20408
30
22
  phoenix/db/insertion/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- phoenix/db/insertion/dataset.py,sha256=2aBOTgjwRkmJqjE1FEQp7BTu1Jz4-bS1bKyeJgvSxfg,7305
32
- phoenix/db/insertion/evaluation.py,sha256=fAerUy3QGf2wID_tiVmPvzxBDFGiONPl3pmpZDgJDWQ,7183
33
- phoenix/db/insertion/helpers.py,sha256=7tf6qQyJ05nn3IXaZEpj2b4Jz5boGLWT8tzlMaJ9tQY,2337
34
- phoenix/db/insertion/span.py,sha256=DNBjSrx5g2W5KuTB1dkHwtkb0SFnMIxN1jB-BAdGKFY,5634
23
+ phoenix/db/insertion/dataset.py,sha256=_vxy5e6W5jEuvO2fMKbbNCn9JvHkwI4LRKk_10eKFVg,7171
24
+ phoenix/db/insertion/evaluation.py,sha256=HoUncZN9ZlIr1QO0uA37SbWhrjmwQVYVJlgFX2VefY8,7211
25
+ phoenix/db/insertion/helpers.py,sha256=5AZQSyTGAthyaIl_l5jL4yva1IrTTBG9y2G7l1r2Yyk,1937
26
+ phoenix/db/insertion/span.py,sha256=d85O3R_Cc3aVFDJSgLLX66qNCPNbKtDxug_dSKFDfew,5655
35
27
  phoenix/db/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
28
  phoenix/db/migrations/env.py,sha256=QbzB5zrRs6XQQmrYeUpuzeilcMlM-MsbaAgHHYcIHTI,3626
37
29
  phoenix/db/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
38
30
  phoenix/db/migrations/types.py,sha256=Frq1AKSyBKQQ0FLzON-EmgTqE4kNkOpHMsbWnI-WgCE,605
39
- phoenix/db/migrations/versions/10460e46d750_datasets.py,sha256=RapdD9Sud_Gq45Vpz7VnDQB_toG6B6yHlwS93qAh_0c,8133
31
+ phoenix/db/migrations/versions/10460e46d750_datasets.py,sha256=l69yZfScFrjfZZpY0gnqwhsDUEctLeo02qMgA_aOGDg,8155
40
32
  phoenix/db/migrations/versions/cf03bd6bae1d_init.py,sha256=CbWT3ZTR0CZqeT3zWLoTWhboFmnOy3Ju1z6Ztpq8WIM,8122
33
+ phoenix/experiments/__init__.py,sha256=6JGwgUd7xCbGpuHqYZlsmErmYvVgv7N_j43bn3dUqsk,123
34
+ phoenix/experiments/functions.py,sha256=w0A6BK80avoupxd3sPJZ_btftV1pXrkbZj4omR_H214,24723
35
+ phoenix/experiments/tracing.py,sha256=wVpt8Ie9WNPoi1djJdcrkwCokHdTO0bicXViLg3O-1Y,2831
36
+ phoenix/experiments/types.py,sha256=tj7DxfsU_nQP5bNe_h6p4KvRjkXKaaB3FeaIerAi_iA,22790
37
+ phoenix/experiments/utils.py,sha256=ZZajvIrZTURhOX5Nx4nyogJEbI18sKCHYiYwOxz2vYU,340
38
+ phoenix/experiments/evaluators/__init__.py,sha256=j63fi3fa3U7-itVPHa82GowhjQRU-wO6yhO34u_lhsA,714
39
+ phoenix/experiments/evaluators/base.py,sha256=uhO4R06YWBbTxdpvXLldANnTxTA5r2h_Ktj-ZMLH57c,5305
40
+ phoenix/experiments/evaluators/code_evaluators.py,sha256=0qIKQS14Knze50ziJEPVEnNeV3QIs4g1IXtCmaWZu7o,3923
41
+ phoenix/experiments/evaluators/llm_evaluators.py,sha256=EFce6LKZwUZDBa5ZozvcdqeZpdWM6n6bmq7_oIzM2Nw,9211
42
+ phoenix/experiments/evaluators/utils.py,sha256=o84UTWN7fzjCGZDTS-KpGZ2VBrk2iSuO3X2LoC7pr3Y,6966
41
43
  phoenix/inferences/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
44
  phoenix/inferences/errors.py,sha256=cGp9vxnw4SewFoWBV3ZGMkhE0Kh73lPIv3Ppz_H_RoA,8261
43
45
  phoenix/inferences/fixtures.py,sha256=FC2eRL4dpobKQHYOilFtDexUWFkMZ_w6jun_4WkbMk0,20792
@@ -58,18 +60,19 @@ phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYG
58
60
  phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
59
61
  phoenix/pointcloud/umap_parameters.py,sha256=lJsEOrbSuSiqI7g4Yt6xj7kgYxEqoep4ZHWLr6VWBqw,1760
60
62
  phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
- phoenix/server/app.py,sha256=_D2DgupKJHv8DmS6VgWxvygumSM75qdlDg6qSj61PRU,18227
63
+ phoenix/server/app.py,sha256=Ld9NvW7sBT4aJn8CXAB_PIw4c5wlkxCcjT_hzjtn7dM,18478
62
64
  phoenix/server/grpc_server.py,sha256=faktLxEtWGlCB1bPR4QwwTsRoQloahKMx0hAWqRGI5s,3379
63
65
  phoenix/server/main.py,sha256=mtzH_2Kyvuy3AHiiKfqiCdUQ6SGFzeT4q9fefbV6GLg,11114
64
66
  phoenix/server/prometheus.py,sha256=j9DHB2fERuq_ZKmwVaqR-9wx5WcPPuU1Cm5Bhg5241Y,2996
65
67
  phoenix/server/telemetry.py,sha256=T_2OKrxNViAeaANlNspEekg_Y5uZIFWvKAnpz8Aoqvk,2762
66
68
  phoenix/server/thread_server.py,sha256=dP6cm6Cf08jNhDA1TRlVZpziu1YgtPDmaeIJMm725eI,2154
67
69
  phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
- phoenix/server/api/context.py,sha256=GfAD9QHg5erKwYGpqDj_8bL2GwmccARDZQc8yO-4Fm0,2669
70
+ phoenix/server/api/context.py,sha256=4jcy203Gtx38399FP21iU3HmFsq-50EKFJlX4IW2Los,2878
69
71
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
70
72
  phoenix/server/api/queries.py,sha256=wp5BlapuxDIoaQJm7mzG0dURfVxR32vXSJVC0JqG4_Y,19845
71
73
  phoenix/server/api/schema.py,sha256=BcxdqO5CSGqpKd-AAJHMjFlzaK9oJA8GJuxmMfcdjn4,434
72
- phoenix/server/api/dataloaders/__init__.py,sha256=9fFjDNlCtOYTOKJi0uPIRh7xJMpCnrBOhoWGEdv1BrI,4618
74
+ phoenix/server/api/dataloaders/__init__.py,sha256=qehXL37vGdw7v5PFs3kbZVIuhuzrVNVeZACDQjYpwyo,4847
75
+ phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=RiO0AKC6Y5byafsV0zTJEIOt8Nudjte73f1T78cBe1k,1817
73
76
  phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=Vpr5IEKSR4QnAVxE5NM7u92fPNgeHQV2ieYc6JakCj0,3788
74
77
  phoenix/server/api/dataloaders/dataset_example_spans.py,sha256=_jLlo0KdUS65d4PNTtE9aXVyG_NZWgA7VcpNC9udQ8U,1484
75
78
  phoenix/server/api/dataloaders/document_evaluation_summaries.py,sha256=dgAAlD0n8X6oAPLaD-czoefNkDqP338MouWsKaW8bOY,5684
@@ -78,6 +81,7 @@ phoenix/server/api/dataloaders/document_retrieval_metrics.py,sha256=8tZYMNLZ7zxU
78
81
  phoenix/server/api/dataloaders/evaluation_summaries.py,sha256=z9aal3IQL_t30aNqpAS7x4tjq0xNkuEG8dWW-bhqZmo,5724
79
82
  phoenix/server/api/dataloaders/experiment_annotation_summaries.py,sha256=RsQ-o84kWVTYgIlh9VKkyw2kDMWIlHCRpS7RE2aw9vs,2881
80
83
  phoenix/server/api/dataloaders/experiment_error_rates.py,sha256=EHlTdZi8F94vo-qJUcnnXFvuSh_d0fTT0Xg4SfW_A70,1397
84
+ phoenix/server/api/dataloaders/experiment_run_counts.py,sha256=wxHv08aZELJ91KTjHdt_x33M3wGDDa9GfbFHeRyOyGk,1343
81
85
  phoenix/server/api/dataloaders/experiment_sequence_number.py,sha256=Va1KuoHOd-wzvrlKykoV4kLRFW4JsJvGp_DUI4HYZX4,1631
82
86
  phoenix/server/api/dataloaders/latency_ms_quantile.py,sha256=pEc7QjB2iiNOQm_Fmo99F5O_DKOJWgGmcnT0OADJzYE,7423
83
87
  phoenix/server/api/dataloaders/min_start_or_max_end_times.py,sha256=IoFX5PtSpvQdMk_7-oB8TpIse3Q4PMxep4qKggkHpzo,2902
@@ -92,9 +96,10 @@ phoenix/server/api/dataloaders/trace_row_ids.py,sha256=yAWuVFWUjDdmmwfXsGs_l6LuG
92
96
  phoenix/server/api/dataloaders/cache/__init__.py,sha256=SYoOM9n8FJaMdQarma5d1blu-jIg2GB8Shqg5ezSzZ8,106
93
97
  phoenix/server/api/dataloaders/cache/two_tier_cache.py,sha256=I38L1RsOis98OQftE7n1Q9QBZfFJO6OW_qIINkuJllo,2295
94
98
  phoenix/server/api/helpers/__init__.py,sha256=_V1eVkchZmTkhOfRC4QqR1sUB2xtIxdsMJkDouZq_IE,251
95
- phoenix/server/api/helpers/dataset_helpers.py,sha256=kIo_kPrV8O40CUypB57JCB5Ek3GJmZXPlz6NIULIsSM,6875
99
+ phoenix/server/api/helpers/dataset_helpers.py,sha256=A6UzEyAb4gFtyc_AV63_yl9OpN0vn8Vw1BBCTNjg9J0,6875
96
100
  phoenix/server/api/input_types/AddExamplesToDatasetInput.py,sha256=ZGXMV0H3DYHi4DdqGhejDzaWdFinyem1Mc8DVA7iCh0,436
97
101
  phoenix/server/api/input_types/AddSpansToDatasetInput.py,sha256=C4oZ0WqYqca1kleNOCMIM2_aY6Qnc5n1xXG51_C1V0w,368
102
+ phoenix/server/api/input_types/ClearProjectInput.py,sha256=cpPFRyQ3ffy2dLbCZgYpway-mCzhdm4QqnUg8caOBfQ,382
98
103
  phoenix/server/api/input_types/ClusterInput.py,sha256=EL4ftvZxQ8mVdruUPcdhMhByORmSmM8S-X6RPqU6GX0,179
99
104
  phoenix/server/api/input_types/Coordinates.py,sha256=meTwbIjwTfqx5DGD2DBlH9wQzdQVNM5a8x9dp1FfIgA,173
100
105
  phoenix/server/api/input_types/CreateDatasetInput.py,sha256=Q3MwouIx9jTQBRWDju75iMQXEGJCrL4aD4ESQp771nc,248
@@ -119,20 +124,20 @@ phoenix/server/api/mutations/auth.py,sha256=vPRFoj7J6PV6QeODewG4K0PhoOebS5AfMRpb
119
124
  phoenix/server/api/mutations/dataset_mutations.py,sha256=Zp2sFWyGyubILUQboR6bafRWafsfeRO2ffUWnkLlfgI,22532
120
125
  phoenix/server/api/mutations/experiment_mutations.py,sha256=Fw_yEdITGJ6A33M5JZ-2YnBTDoBqZUUFON6vy8JoVjE,2569
121
126
  phoenix/server/api/mutations/export_events_mutations.py,sha256=t_wYBxaqvBJYRoHslh3Bmoxmwlzoy0u8SsBKWIKN5hE,4028
122
- phoenix/server/api/mutations/project_mutations.py,sha256=6A7BS3651iaeAwUszKXQB3NK4QJY_tGpALBMNw1bqp8,2021
127
+ phoenix/server/api/mutations/project_mutations.py,sha256=3SVDCZqxB0Iv60cOwBL8c-rY3QUUPs8PXbp-C_K1mWY,2267
123
128
  phoenix/server/api/openapi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
129
  phoenix/server/api/openapi/main.py,sha256=WY0pj3B7siQyyYqKyhqnzWC7P8MtEtiukOBUjGwLXfw,153
125
130
  phoenix/server/api/openapi/schema.py,sha256=uuSYe1Ecu72aXRgTNjyMu-9ZPE13DAHJPKtedS-MsSs,451
126
131
  phoenix/server/api/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
127
132
  phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
128
- phoenix/server/api/routers/v1/__init__.py,sha256=B5eSaylPI7MoYia1-VgKrU8rDi-69r_hRwPU5yMLUTE,2808
129
- phoenix/server/api/routers/v1/dataset_examples.py,sha256=wtplRUv2ee9xGTrcEMgTn-7L4NX_73IcwUXkCMZEFc4,6726
130
- phoenix/server/api/routers/v1/datasets.py,sha256=2wkBOLqo8ttSN1VNVEcnPcLCitkSLGp62AjWlxJhV4Y,27605
131
- phoenix/server/api/routers/v1/evaluations.py,sha256=rwSVg-rpujhsMcDVFt-VAr0Ix9TgvLcY_bSxeh8PzJI,9241
132
- phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=xemnZ10WL5pErndP7jbaDipUj3Tkl813XSIjx7X5MBY,2656
133
- phoenix/server/api/routers/v1/experiment_runs.py,sha256=o6IvcyFDY-cy3KqeO9FIKy3XAgbIJhx7SFUoxML-MeY,4337
134
- phoenix/server/api/routers/v1/experiments.py,sha256=5Rh7q6sHswmk11PZSJ7KMrtqfIE16X_xSKkKSASK9-I,7251
135
- phoenix/server/api/routers/v1/spans.py,sha256=FEnmlRPBPl71BSGNBuPrz14fk8nmxJQYsKECdDbdUdw,3977
133
+ phoenix/server/api/routers/v1/__init__.py,sha256=vvdpUa2LJPWEg8HbvDm_ANkBAwubPIFPbbHi7elOUws,2808
134
+ phoenix/server/api/routers/v1/dataset_examples.py,sha256=XfqOvDKF1oxb0pkeYfBycwwGt3LnSyyGdMLKC5VKoGQ,6690
135
+ phoenix/server/api/routers/v1/datasets.py,sha256=f2gLG-geu-_wtEw4mKSzNWK2cFb5TYOyRL3tQ7Fl7Es,31544
136
+ phoenix/server/api/routers/v1/evaluations.py,sha256=8g6P_e2BweV3RDU0esFmpkb0L5fCwonQPXiJ0y6HLwg,9126
137
+ phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=HeyV3PXS1BxQpzNOUBpQlX_0JH_jbjZjTxrqy2ujwJQ,2746
138
+ phoenix/server/api/routers/v1/experiment_runs.py,sha256=_c7qmPIja_gpvoVaf_t7KtNc9Zz-0m9da9MS-EcbPBo,3918
139
+ phoenix/server/api/routers/v1/experiments.py,sha256=ntb0lRV2h90mFepWiZfQ1MIAJhOaK9tkWzTejmpwed0,7243
140
+ phoenix/server/api/routers/v1/spans.py,sha256=PFeS3ayKj4cUle0CH-f-CpM1fRi-JicEG7BEtkANzAo,4074
136
141
  phoenix/server/api/routers/v1/traces.py,sha256=dYEf5pThenAQCgfQljHdrnwd4tC_tAXm6Kvk6GphPYs,2774
137
142
  phoenix/server/api/types/AnnotatorKind.py,sha256=UmYb2KG0JfxdX0mW1qrXrUoIgjMOncRJr1i8mJki1sE,141
138
143
  phoenix/server/api/types/Cluster.py,sha256=ac4YfT1OH3xLVmex7EUmB6b9IpULnhLTt554LR0jglE,5689
@@ -157,11 +162,11 @@ phoenix/server/api/types/EvaluationSummary.py,sha256=EFucuzAhcxR9sdEn6WNAtmAGJk-
157
162
  phoenix/server/api/types/Event.py,sha256=XdYgaIxcVIW-YFViCkxj5l9OaVNepyIrCtm5Iqg2le8,3989
158
163
  phoenix/server/api/types/EventMetadata.py,sha256=-J0tYF9eZTHwCjwxQHY7Gckr2_MNW5OoWT1mydweZNM,635
159
164
  phoenix/server/api/types/ExampleRevisionInterface.py,sha256=gV3Gt9-3Oi5wjaVtepC6nOt3FzTzZFD1KebNnqiw56E,294
160
- phoenix/server/api/types/Experiment.py,sha256=Lon2ZNZYdWXQmj3nLr_TXN8CCtZtC-AXYfyJuoqI2DM,4692
165
+ phoenix/server/api/types/Experiment.py,sha256=ELYdYFKwgBllxx3cZ_X0XicHjLtshZl0bFqqJdVGXRQ,5177
161
166
  phoenix/server/api/types/ExperimentAnnotationSummary.py,sha256=Uk3JtxIrsMoZT5tqc4nJdUOM3XegVzjUyoV3pkjNotE,256
162
167
  phoenix/server/api/types/ExperimentComparison.py,sha256=0sFz6MoBDw39dds0qVyaqhVs9qqO5rkG1FMSjmfBeCc,441
163
- phoenix/server/api/types/ExperimentRun.py,sha256=uM7HxaC8nEjtO7yLr8WjLEfYRvEvbX6ibR8I0fVzdeU,2976
164
- phoenix/server/api/types/ExperimentRunAnnotation.py,sha256=GvWY6wukBhSr2Tk9Ef0R5bH5yCMxVakqeypoyYoUb6o,1774
168
+ phoenix/server/api/types/ExperimentRun.py,sha256=8jUIi3ApVCqQHwnYe59CYhrmh5iZ6-QmlH5WpF7UWtM,2990
169
+ phoenix/server/api/types/ExperimentRunAnnotation.py,sha256=zGstMbS5OxNikEhD8VouY7Ls7YbxKm-0EmqvGeY3-DI,1773
165
170
  phoenix/server/api/types/ExportedFile.py,sha256=e3GTn7B5LgsTbqiwjhMCQH7VsiqXitrBO4aCMS1lHsg,163
166
171
  phoenix/server/api/types/Functionality.py,sha256=tzV9xdhB8zqfsjWxP66NDC7EZsplYkYO7jRbLWJIeeg,382
167
172
  phoenix/server/api/types/Inferences.py,sha256=HWuDZZrXPWVoEy_pA3bRsAOUYsCKgAxf9zshasGqu5Y,3403
@@ -197,12 +202,12 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
197
202
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
198
203
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
199
204
  phoenix/server/static/index.css,sha256=KKGpx4iwF91VGRm0YN-4cn8oC-oIqC6HecoPf0x3ZM8,1885
200
- phoenix/server/static/index.js,sha256=n8qF_l7ijW-7E8m63oViD8SpXOYjN3wvZUhgB8H6ZLo,3489949
205
+ phoenix/server/static/index.js,sha256=qAPO3xGdQ2mIA8TcIPNkIfLvoGeZ78fVKbGZevfJzoM,3518643
201
206
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
202
207
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
208
  phoenix/server/templates/index.html,sha256=S4z7qSoNSwnKFAH9r96AR-YJEyoKMd-VMWVlJ_IdzME,2039
204
209
  phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
- phoenix/session/client.py,sha256=tq2qghwYa_mxNYLD41UNfD7n57msB9lYIe5H16lBqoo,20333
210
+ phoenix/session/client.py,sha256=5mnWVqMFbC8NYbX4m2oRla1VvlmrgabD1oT2UdwDRJ8,33201
206
211
  phoenix/session/data_extractor.py,sha256=dwhiDu-ISaXr8UI9I-CszZhB5BlUNmdDopjFZvMIXMw,2101
207
212
  phoenix/session/evaluation.py,sha256=aKeV8UVOyq3b7CYOwt3cWuLz0xzvMjX7vlEPILJ_fcs,5311
208
213
  phoenix/session/session.py,sha256=rjIuSSK2gAYIUPQTJc4E2ebew5o6I070FWRoFn4W3EI,26620
@@ -211,7 +216,7 @@ phoenix/trace/attributes.py,sha256=xSr2EvlkDS9Wiij7FywXzw7UmMAMLIARSEm_P686BKM,1
211
216
  phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
212
217
  phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
213
218
  phoenix/trace/exporter.py,sha256=eAYemdvDCHMugDJiaR29BFFMTQBdf3oerdkz34Cl3hE,4736
214
- phoenix/trace/fixtures.py,sha256=gBGFG2gkcBsSDzolzzR9AJDrB_fdOQfUaGgHV-EHdco,14204
219
+ phoenix/trace/fixtures.py,sha256=tDso17oAYMBQ8GJsAlHFzrC0otXPzUOEh4TgIjEfB7M,14260
215
220
  phoenix/trace/otel.py,sha256=WA720jvRadiZBAKjsYoPyXzypHwbyEK2OZRVUwtbjB8,9976
216
221
  phoenix/trace/projects.py,sha256=2BwlNjFE-uwpqYtCu5YyBiYZk9wRPpM13vh3-Cv7GkA,2157
217
222
  phoenix/trace/schemas.py,sha256=Mjc6fD9OyeMnEk5wPPSbveqnNUYWK3p3BxpOvSGanHU,5950
@@ -237,13 +242,13 @@ phoenix/trace/v1/evaluation_pb2.pyi,sha256=cCbbx06gwQmaH14s3J1X25TtaARh-k1abbxQd
237
242
  phoenix/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
238
243
  phoenix/utilities/deprecation.py,sha256=cFuTVvjSYyRlrdxdJewjJVieIEHPk30BukSRGRydQ3k,1046
239
244
  phoenix/utilities/error_handling.py,sha256=7b5rpGFj9EWZ8yrZK1IHvxB89suWk3lggDayUQcvZds,1946
240
- phoenix/utilities/json.py,sha256=nuD1SbPm871tbt9Cz7V2NUmS9m0jWgcpRUx1YOV3NYQ,1954
245
+ phoenix/utilities/json.py,sha256=y_w-McDfvlTeGJT28sCtyjzVkwFicakxERG-sGRc8Ak,1948
241
246
  phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,222
242
247
  phoenix/utilities/project.py,sha256=qWsvKnG1oKhOFUowXf9qiOL2ia7jaFe_ijFFHEt8GJo,431
243
248
  phoenix/utilities/re.py,sha256=PDve_OLjRTM8yQQJHC8-n3HdIONi7aNils3ZKRZ5uBM,2045
244
249
  phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
245
- arize_phoenix-4.4.4rc4.dist-info/METADATA,sha256=YEUoxXSRba4zRgzM8-lcq7TIp9GNPZSjY_QGoyIJN-w,11012
246
- arize_phoenix-4.4.4rc4.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
247
- arize_phoenix-4.4.4rc4.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
248
- arize_phoenix-4.4.4rc4.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
249
- arize_phoenix-4.4.4rc4.dist-info/RECORD,,
250
+ arize_phoenix-4.4.4rc6.dist-info/METADATA,sha256=gyc5KyS4aFqefmGcezl1eC_8lCZ5DF0iHdSDh0V41f8,11337
251
+ arize_phoenix-4.4.4rc6.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
252
+ arize_phoenix-4.4.4rc6.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
253
+ arize_phoenix-4.4.4rc6.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
254
+ arize_phoenix-4.4.4rc6.dist-info/RECORD,,
phoenix/config.py CHANGED
@@ -233,4 +233,25 @@ def get_env_client_headers() -> Optional[Dict[str, str]]:
233
233
  return None
234
234
 
235
235
 
236
+ def get_base_url() -> str:
237
+ host = get_env_host()
238
+ if host == "0.0.0.0":
239
+ host = "127.0.0.1"
240
+ base_url = get_env_collector_endpoint() or f"http://{host}:{get_env_port()}"
241
+ return base_url if base_url.endswith("/") else base_url + "/"
242
+
243
+
244
+ def get_web_base_url() -> str:
245
+ """Return the web UI base URL.
246
+
247
+ Returns:
248
+ str: the web UI base URL
249
+ """
250
+ from phoenix.session.session import active_session
251
+
252
+ if session := active_session():
253
+ return session.url
254
+ return get_base_url()
255
+
256
+
236
257
  DEFAULT_PROJECT_NAME = "default"
phoenix/datetime_utils.py CHANGED
@@ -14,6 +14,10 @@ from pandas.core.dtypes.common import (
14
14
  _LOCAL_TIMEZONE = datetime.now(timezone.utc).astimezone().tzinfo
15
15
 
16
16
 
17
+ def local_now() -> datetime:
18
+ return datetime.now(timezone.utc).astimezone(tz=_LOCAL_TIMEZONE)
19
+
20
+
17
21
  def normalize_datetime(
18
22
  dt: Optional[datetime],
19
23
  tz: Optional[tzinfo] = None,
@@ -1,17 +1,17 @@
1
1
  import logging
2
- from dataclasses import dataclass
2
+ from dataclasses import dataclass, field
3
3
  from datetime import datetime, timezone
4
4
  from enum import Enum
5
5
  from itertools import chain
6
6
  from typing import (
7
7
  Any,
8
8
  Awaitable,
9
+ Dict,
9
10
  FrozenSet,
10
11
  Iterable,
11
12
  Iterator,
12
13
  Mapping,
13
14
  Optional,
14
- Sequence,
15
15
  Union,
16
16
  cast,
17
17
  )
@@ -30,7 +30,16 @@ DatasetVersionId: TypeAlias = int
30
30
  DatasetExampleId: TypeAlias = int
31
31
  DatasetExampleRevisionId: TypeAlias = int
32
32
  SpanRowId: TypeAlias = int
33
- Examples: TypeAlias = Iterable[Mapping[str, Any]]
33
+
34
+
35
+ @dataclass(frozen=True)
36
+ class ExampleContent:
37
+ input: Dict[str, Any] = field(default_factory=dict)
38
+ output: Dict[str, Any] = field(default_factory=dict)
39
+ metadata: Dict[str, Any] = field(default_factory=dict)
40
+
41
+
42
+ Examples: TypeAlias = Iterable[ExampleContent]
34
43
 
35
44
 
36
45
  @dataclass(frozen=True)
@@ -149,14 +158,10 @@ async def add_dataset_examples(
149
158
  session: AsyncSession,
150
159
  name: str,
151
160
  examples: Union[Examples, Awaitable[Examples]],
152
- input_keys: Sequence[str],
153
- output_keys: Sequence[str],
154
- metadata_keys: Sequence[str] = (),
155
161
  description: Optional[str] = None,
156
162
  metadata: Optional[Mapping[str, Any]] = None,
157
163
  action: DatasetAction = DatasetAction.CREATE,
158
164
  ) -> Optional[DatasetExampleAdditionEvent]:
159
- keys = DatasetKeys(frozenset(input_keys), frozenset(output_keys), frozenset(metadata_keys))
160
165
  created_at = datetime.now(timezone.utc)
161
166
  dataset_id: Optional[DatasetId] = None
162
167
  if action is DatasetAction.APPEND and name:
@@ -173,9 +178,7 @@ async def add_dataset_examples(
173
178
  created_at=created_at,
174
179
  )
175
180
  except Exception:
176
- logger.exception(
177
- f"Fail to insert dataset: {input_keys=}, {output_keys=}, {metadata_keys=}"
178
- )
181
+ logger.exception(f"Failed to insert dataset: {name=}")
179
182
  raise
180
183
  try:
181
184
  dataset_version_id = await insert_dataset_version(
@@ -184,7 +187,7 @@ async def add_dataset_examples(
184
187
  created_at=created_at,
185
188
  )
186
189
  except Exception:
187
- logger.exception(f"Fail to insert dataset version for {dataset_id=}")
190
+ logger.exception(f"Failed to insert dataset version for {dataset_id=}")
188
191
  raise
189
192
  for example in (await examples) if isinstance(examples, Awaitable) else examples:
190
193
  try:
@@ -194,21 +197,21 @@ async def add_dataset_examples(
194
197
  created_at=created_at,
195
198
  )
196
199
  except Exception:
197
- logger.exception(f"Fail to insert dataset example for {dataset_id=}")
200
+ logger.exception(f"Failed to insert dataset example for {dataset_id=}")
198
201
  raise
199
202
  try:
200
203
  await insert_dataset_example_revision(
201
204
  session=session,
202
205
  dataset_version_id=dataset_version_id,
203
206
  dataset_example_id=dataset_example_id,
204
- input={key: example.get(key) for key in keys.input},
205
- output={key: example.get(key) for key in keys.output},
206
- metadata={key: example.get(key) for key in keys.metadata},
207
+ input=example.input,
208
+ output=example.output,
209
+ metadata=example.metadata,
207
210
  created_at=created_at,
208
211
  )
209
212
  except Exception:
210
213
  logger.exception(
211
- f"Fail to insert dataset example revision for {dataset_version_id=}, "
214
+ f"Failed to insert dataset example revision for {dataset_version_id=}, "
212
215
  f"{dataset_example_id=}"
213
216
  )
214
217
  raise
@@ -6,7 +6,7 @@ from typing_extensions import assert_never
6
6
 
7
7
  from phoenix.db import models
8
8
  from phoenix.db.helpers import SupportedSQLDialect, num_docs_col
9
- from phoenix.db.insertion.helpers import OnConflict, insert_stmt
9
+ from phoenix.db.insertion.helpers import OnConflict, insert_on_conflict
10
10
  from phoenix.exceptions import PhoenixException
11
11
  from phoenix.trace import v1 as pb
12
12
 
@@ -91,7 +91,7 @@ async def _insert_trace_evaluation(
91
91
  set_.pop("metadata_")
92
92
  set_["metadata"] = values["metadata_"] # `metadata` must match database
93
93
  await session.execute(
94
- insert_stmt(
94
+ insert_on_conflict(
95
95
  dialect=dialect,
96
96
  table=models.TraceAnnotation,
97
97
  values=values,
@@ -139,7 +139,7 @@ async def _insert_span_evaluation(
139
139
  set_.pop("metadata_")
140
140
  set_["metadata"] = values["metadata_"] # `metadata` must match database
141
141
  await session.execute(
142
- insert_stmt(
142
+ insert_on_conflict(
143
143
  dialect=dialect,
144
144
  table=models.SpanAnnotation,
145
145
  values=values,
@@ -196,7 +196,7 @@ async def _insert_document_evaluation(
196
196
  set_.pop("metadata_")
197
197
  set_["metadata"] = values["metadata_"] # `metadata` must match database
198
198
  await session.execute(
199
- insert_stmt(
199
+ insert_on_conflict(
200
200
  dialect=dialect,
201
201
  table=models.DocumentAnnotation,
202
202
  values=values,
@@ -2,7 +2,7 @@ from abc import ABC
2
2
  from enum import Enum, auto
3
3
  from typing import Any, Awaitable, Callable, Mapping, Optional, Sequence
4
4
 
5
- from sqlalchemy import Insert, insert
5
+ from sqlalchemy import Insert
6
6
  from sqlalchemy.dialects.postgresql import insert as insert_postgresql
7
7
  from sqlalchemy.dialects.sqlite import insert as insert_sqlite
8
8
  from sqlalchemy.ext.asyncio import AsyncSession
@@ -25,26 +25,18 @@ class OnConflict(Enum):
25
25
  DO_UPDATE = auto()
26
26
 
27
27
 
28
- def insert_stmt(
28
+ def insert_on_conflict(
29
29
  dialect: SupportedSQLDialect,
30
30
  table: Any,
31
31
  values: Mapping[str, Any],
32
- constraint: Optional[str] = None,
33
- column_names: Sequence[str] = (),
32
+ constraint: str,
33
+ column_names: Sequence[str],
34
34
  on_conflict: OnConflict = OnConflict.DO_NOTHING,
35
35
  set_: Optional[Mapping[str, Any]] = None,
36
36
  ) -> Insert:
37
37
  """
38
38
  Dialect specific insertion statement using ON CONFLICT DO syntax.
39
39
  """
40
- if bool(constraint) != bool(column_names):
41
- raise ValueError(
42
- "Both `constraint` and `column_names` must be provided or omitted at the same time."
43
- )
44
- if (dialect is SupportedSQLDialect.POSTGRESQL and constraint is None) or (
45
- dialect is SupportedSQLDialect.SQLITE and not column_names
46
- ):
47
- return insert(table).values(values)
48
40
  if dialect is SupportedSQLDialect.POSTGRESQL:
49
41
  stmt_postgresql = insert_postgresql(table).values(values)
50
42
  if on_conflict is OnConflict.DO_NOTHING or not set_:
@@ -7,7 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
7
7
 
8
8
  from phoenix.db import models
9
9
  from phoenix.db.helpers import SupportedSQLDialect
10
- from phoenix.db.insertion.helpers import OnConflict, insert_stmt
10
+ from phoenix.db.insertion.helpers import OnConflict, insert_on_conflict
11
11
  from phoenix.trace.attributes import get_attribute_value
12
12
  from phoenix.trace.schemas import Span, SpanStatusCode
13
13
 
@@ -27,7 +27,7 @@ async def insert_span(
27
27
  ) -> Optional[SpanInsertionEvent]:
28
28
  dialect = SupportedSQLDialect(session.bind.dialect.name)
29
29
  project_rowid = await session.scalar(
30
- insert_stmt(
30
+ insert_on_conflict(
31
31
  dialect=dialect,
32
32
  table=models.Project,
33
33
  constraint="uq_projects_name",
@@ -87,7 +87,7 @@ async def insert_span(
87
87
  cumulative_llm_token_count_prompt += cast(int, accumulation[1] or 0)
88
88
  cumulative_llm_token_count_completion += cast(int, accumulation[2] or 0)
89
89
  span_rowid = await session.scalar(
90
- insert_stmt(
90
+ insert_on_conflict(
91
91
  dialect=dialect,
92
92
  table=models.Span,
93
93
  constraint="uq_spans_span_id",
@@ -72,7 +72,7 @@ def upgrade() -> None:
72
72
  sa.Column(
73
73
  "span_rowid",
74
74
  sa.Integer,
75
- sa.ForeignKey("spans.id"),
75
+ sa.ForeignKey("spans.id", ondelete="SET NULL"),
76
76
  nullable=True,
77
77
  index=True,
78
78
  ),
@@ -198,7 +198,7 @@ def upgrade() -> None:
198
198
  sa.String,
199
199
  nullable=True,
200
200
  ),
201
- sa.Column("output", JSON_, nullable=True),
201
+ sa.Column("output", JSON_, nullable=False),
202
202
  sa.Column("start_time", sa.TIMESTAMP(timezone=True), nullable=False),
203
203
  sa.Column("end_time", sa.TIMESTAMP(timezone=True), nullable=False),
204
204
  sa.Column(
phoenix/db/models.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from datetime import datetime, timezone
2
- from typing import Any, Dict, List, Optional
2
+ from typing import Any, Dict, List, Optional, TypedDict
3
3
 
4
4
  from sqlalchemy import (
5
5
  JSON,
@@ -91,6 +91,10 @@ class UtcTimeStamp(TypeDecorator[datetime]):
91
91
  return normalize_datetime(value, timezone.utc)
92
92
 
93
93
 
94
+ class ExperimentResult(TypedDict, total=False):
95
+ result: Any
96
+
97
+
94
98
  class Base(DeclarativeBase):
95
99
  # Enforce best practices for naming constraints
96
100
  # https://alembic.sqlalchemy.org/en/latest/naming.html#integration-of-naming-conventions-into-operations-autogenerate
@@ -106,6 +110,7 @@ class Base(DeclarativeBase):
106
110
  type_annotation_map = {
107
111
  Dict[str, Any]: JsonDict,
108
112
  List[Dict[str, Any]]: JsonList,
113
+ ExperimentResult: JsonDict,
109
114
  }
110
115
 
111
116
 
@@ -483,7 +488,7 @@ class DatasetExample(Base):
483
488
  index=True,
484
489
  )
485
490
  span_rowid: Mapped[Optional[int]] = mapped_column(
486
- ForeignKey("spans.id"),
491
+ ForeignKey("spans.id", ondelete="SET NULL"),
487
492
  index=True,
488
493
  nullable=True,
489
494
  )
@@ -556,7 +561,7 @@ class ExperimentRun(Base):
556
561
  )
557
562
  repetition_number: Mapped[int]
558
563
  trace_id: Mapped[Optional[str]]
559
- output: Mapped[Optional[Dict[str, Any]]]
564
+ output: Mapped[ExperimentResult]
560
565
  start_time: Mapped[datetime] = mapped_column(UtcTimeStamp)
561
566
  end_time: Mapped[datetime] = mapped_column(UtcTimeStamp)
562
567
  prompt_token_count: Mapped[Optional[int]]
@@ -0,0 +1,6 @@
1
+ from .functions import evaluate_experiment, run_experiment
2
+
3
+ __all__ = [
4
+ "evaluate_experiment",
5
+ "run_experiment",
6
+ ]
@@ -0,0 +1,29 @@
1
+ from phoenix.experiments.evaluators.code_evaluators import (
2
+ ContainsAllKeywords,
3
+ ContainsAnyKeyword,
4
+ ContainsKeyword,
5
+ JSONParsable,
6
+ MatchesRegex,
7
+ )
8
+ from phoenix.experiments.evaluators.llm_evaluators import (
9
+ CoherenceEvaluator,
10
+ ConcisenessEvaluator,
11
+ HelpfulnessEvaluator,
12
+ LLMCriteriaEvaluator,
13
+ RelevanceEvaluator,
14
+ )
15
+ from phoenix.experiments.evaluators.utils import create_evaluator
16
+
17
+ __all__ = [
18
+ "create_evaluator",
19
+ "ContainsAllKeywords",
20
+ "ContainsAnyKeyword",
21
+ "ContainsKeyword",
22
+ "JSONParsable",
23
+ "MatchesRegex",
24
+ "CoherenceEvaluator",
25
+ "ConcisenessEvaluator",
26
+ "LLMCriteriaEvaluator",
27
+ "HelpfulnessEvaluator",
28
+ "RelevanceEvaluator",
29
+ ]