arize-phoenix 2.0.0__py3-none-any.whl → 2.2.0rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/METADATA +5 -1
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/RECORD +31 -29
- phoenix/__init__.py +2 -2
- phoenix/core/evals.py +29 -8
- phoenix/core/traces.py +45 -34
- phoenix/experimental/evals/__init__.py +4 -1
- phoenix/experimental/evals/evaluators.py +85 -8
- phoenix/experimental/evals/functions/classify.py +16 -41
- phoenix/experimental/evals/functions/executor.py +1 -0
- phoenix/experimental/evals/models/anthropic.py +171 -0
- phoenix/experimental/evals/models/vertex.py +155 -0
- phoenix/experimental/evals/templates/__init__.py +2 -0
- phoenix/experimental/evals/templates/default_templates.py +12 -0
- phoenix/experimental/evals/utils/__init__.py +64 -2
- phoenix/server/api/schema.py +24 -0
- phoenix/server/app.py +6 -5
- phoenix/server/main.py +6 -7
- phoenix/server/span_handler.py +7 -7
- phoenix/server/static/index.js +586 -499
- phoenix/server/templates/index.html +5 -1
- phoenix/server/trace_handler.py +56 -0
- phoenix/session/session.py +2 -1
- phoenix/trace/exporter.py +4 -3
- phoenix/trace/langchain/tracer.py +14 -4
- phoenix/trace/otel.py +409 -0
- phoenix/trace/semantic_conventions.py +2 -0
- phoenix/trace/v1/__init__.py +0 -4
- phoenix/version.py +1 -0
- phoenix/trace/v1/trace_pb2.py +0 -54
- phoenix/trace/v1/trace_pb2.pyi +0 -361
- phoenix/trace/v1/utils.py +0 -538
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/WHEEL +0 -0
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: arize-phoenix
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0rc0
|
|
4
4
|
Summary: ML Observability in your notebook
|
|
5
5
|
Project-URL: Documentation, https://docs.arize.com/phoenix/
|
|
6
6
|
Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
|
|
@@ -20,6 +20,8 @@ Requires-Dist: ddsketch
|
|
|
20
20
|
Requires-Dist: hdbscan<1.0.0,>=0.8.33
|
|
21
21
|
Requires-Dist: jinja2
|
|
22
22
|
Requires-Dist: numpy
|
|
23
|
+
Requires-Dist: opentelemetry-proto
|
|
24
|
+
Requires-Dist: opentelemetry-sdk
|
|
23
25
|
Requires-Dist: pandas
|
|
24
26
|
Requires-Dist: protobuf<5.0,>=3.20
|
|
25
27
|
Requires-Dist: psutil
|
|
@@ -36,8 +38,10 @@ Requires-Dist: umap-learn
|
|
|
36
38
|
Requires-Dist: uvicorn
|
|
37
39
|
Requires-Dist: wrapt
|
|
38
40
|
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: anthropic; extra == 'dev'
|
|
39
42
|
Requires-Dist: arize[autoembeddings,llm-evaluation]; extra == 'dev'
|
|
40
43
|
Requires-Dist: gcsfs; extra == 'dev'
|
|
44
|
+
Requires-Dist: google-cloud-aiplatform>=1.3; extra == 'dev'
|
|
41
45
|
Requires-Dist: hatch; extra == 'dev'
|
|
42
46
|
Requires-Dist: jupyter; extra == 'dev'
|
|
43
47
|
Requires-Dist: langchain>=0.0.334; extra == 'dev'
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
phoenix/__init__.py,sha256=
|
|
1
|
+
phoenix/__init__.py,sha256=EEh0vZGRQS8686h34GQ64OjQoZ7neKYO_iO5j6Oa9Jw,1402
|
|
2
2
|
phoenix/config.py,sha256=ErvGg22SSiuqPJtIX1WZE5KcM2lt6XOGZ__HwRg3JqA,2390
|
|
3
3
|
phoenix/datetime_utils.py,sha256=D955QLrkgrrSdUM6NyqbCeAu2SMsjhR5rHVQEsVUdng,2773
|
|
4
4
|
phoenix/exceptions.py,sha256=igIWGAg3m8jm5YwQDeCY1p8ml_60A7zaGVXJ1yZhY9s,44
|
|
5
5
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
6
6
|
phoenix/services.py,sha256=slL4Uu___QQSKEssgD738-WAld-kzVQnpW92uKLxV4E,4886
|
|
7
|
+
phoenix/version.py,sha256=pG4VqwySwU54SQ_mHFbajVD0oK3-38mb_fLPwWYLdoc,25
|
|
7
8
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
9
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
9
|
-
phoenix/core/evals.py,sha256=
|
|
10
|
+
phoenix/core/evals.py,sha256=OrHeYlh804rpcZIXTA6kan2mzSZMfgpphNNQdPMpNoM,7597
|
|
10
11
|
phoenix/core/model.py,sha256=vQ6RxpUPlncezJvur5u6xBN0Lkrk2gW0cTyb-qqaSqA,4713
|
|
11
12
|
phoenix/core/model_schema.py,sha256=rR9VdhL_oXxbprDTPQJBXs5hw5sMPQmzx__m6Kwsxug,50394
|
|
12
13
|
phoenix/core/model_schema_adapter.py,sha256=3GkyzqUST4fYi-Bgs8qAam5hwMCdQRZTDLjZ9Bnzdm4,8268
|
|
13
|
-
phoenix/core/traces.py,sha256=
|
|
14
|
+
phoenix/core/traces.py,sha256=O01L6qwQfHxHUHNZemKBBsAgqDo1tAIO5-1fK2g0NwE,14618
|
|
14
15
|
phoenix/datasets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
16
|
phoenix/datasets/dataset.py,sha256=scKVZ7zc6Dpc_ntt-pWhzY-KWqOJEwKePuyNnKSVTGE,30515
|
|
16
17
|
phoenix/datasets/errors.py,sha256=cGp9vxnw4SewFoWBV3ZGMkhE0Kh73lPIv3Ppz_H_RoA,8261
|
|
@@ -18,25 +19,27 @@ phoenix/datasets/fixtures.py,sha256=0_PacL3dw49zulKpFpPdhvxJxeGmHTguqIyf2VXkBkk,
|
|
|
18
19
|
phoenix/datasets/schema.py,sha256=bF1d2Md6NyqQZuC4Ym5A52f2_IcazkyxGFZ11HPqSg0,6668
|
|
19
20
|
phoenix/datasets/validation.py,sha256=dZ9lCFUV0EY7HCkQkQBrs-GLAEIZdpOqUxwD5l4dp88,8294
|
|
20
21
|
phoenix/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
phoenix/experimental/evals/__init__.py,sha256=
|
|
22
|
-
phoenix/experimental/evals/evaluators.py,sha256=
|
|
22
|
+
phoenix/experimental/evals/__init__.py,sha256=I-e_QhT3ezMwc0WeqZuTNbuHkdaLj9WvnFCv6aNAmYM,1595
|
|
23
|
+
phoenix/experimental/evals/evaluators.py,sha256=rLvvXBK2H_cjJyRMBQStTlMYntTJI3RtukwJopeA1jU,13065
|
|
23
24
|
phoenix/experimental/evals/retrievals.py,sha256=o3fqrsYbYZjyGj_jWkN_9VQVyXjLkDKDw5Ws7l8bwdI,3828
|
|
24
25
|
phoenix/experimental/evals/functions/__init__.py,sha256=3FMGrjmgxegXAwgDV_RpaN-73cFVyBiO8YwZvml5P9c,156
|
|
25
|
-
phoenix/experimental/evals/functions/classify.py,sha256=
|
|
26
|
-
phoenix/experimental/evals/functions/executor.py,sha256=
|
|
26
|
+
phoenix/experimental/evals/functions/classify.py,sha256=uCTZR_ctQorzS0Abcwxzsza0g-4q_91DHiObjJISIXE,18177
|
|
27
|
+
phoenix/experimental/evals/functions/executor.py,sha256=bM7PI2rcPukQQzZ2rWqN_-Kfo_a935YJj0bh1Red8Ps,13406
|
|
27
28
|
phoenix/experimental/evals/functions/generate.py,sha256=sdr6TeXn5JLEKM0NqYtvq01Lq48Q7uatb0fsq5zQgVY,5310
|
|
28
29
|
phoenix/experimental/evals/functions/processing.py,sha256=F4xtLsulLV4a8CkuLldRddsCim75dSTIShEJUYN6I6w,1823
|
|
29
30
|
phoenix/experimental/evals/models/__init__.py,sha256=j1N7DhiOPbcaemtVBONcQ0miNnGQwEXz4u3P3Vwe6-4,320
|
|
31
|
+
phoenix/experimental/evals/models/anthropic.py,sha256=Tcv8R-vTyY8sLAv1wIHeZdMCBtqhyayqMPJXRDc7blI,6267
|
|
30
32
|
phoenix/experimental/evals/models/base.py,sha256=aSE3Al3MsLvzNKuN2e-z6O-RB5mgpisH4UQqwNQcqp0,7734
|
|
31
33
|
phoenix/experimental/evals/models/bedrock.py,sha256=CRPmBuSLc_nRnKKWLHhGMxdWEISIKUJM1tzIlOQ_qWM,7927
|
|
32
34
|
phoenix/experimental/evals/models/litellm.py,sha256=jrRlph22xWxMXMUabUWjIO2e-sHxQzlQwSM-SnAACFQ,4714
|
|
33
35
|
phoenix/experimental/evals/models/openai.py,sha256=Kl2uES3HRcZGFqblfBQZ6D1BpDffuLZDAqVTjhrSXXQ,17101
|
|
34
36
|
phoenix/experimental/evals/models/rate_limiters.py,sha256=5GVN0RQKt36Przg3-9jLgocRmyg-tbeO-cdbuLIx89w,10160
|
|
37
|
+
phoenix/experimental/evals/models/vertex.py,sha256=nwTIjVn4gGFfoKfGqUGwPD9GLJaBM4HLXDnMNs9hSrw,5407
|
|
35
38
|
phoenix/experimental/evals/models/vertexai.py,sha256=NfBpQq0l7XzP-wDEDsK27IRiQBzA1GXEdfwlAf8leX4,5609
|
|
36
|
-
phoenix/experimental/evals/templates/__init__.py,sha256
|
|
37
|
-
phoenix/experimental/evals/templates/default_templates.py,sha256=
|
|
39
|
+
phoenix/experimental/evals/templates/__init__.py,sha256=GSJSoWJ4jwyoUANniidmWMUtXQhNQYbTJbfFqCvuYuo,1470
|
|
40
|
+
phoenix/experimental/evals/templates/default_templates.py,sha256=_VVxuhPsY8fkasA9XMNNM_fvftltkIfVCfElSdFbsQY,21056
|
|
38
41
|
phoenix/experimental/evals/templates/template.py,sha256=VAX_ZeV3vNWCODipMy7EtaYdQ0c7WA6H2Mx0i1axXf0,6005
|
|
39
|
-
phoenix/experimental/evals/utils/__init__.py,sha256=
|
|
42
|
+
phoenix/experimental/evals/utils/__init__.py,sha256=608EX7sG0f5oDG__II16J8xnFJiNpY9dI9AC8vXwR00,5601
|
|
40
43
|
phoenix/experimental/evals/utils/threads.py,sha256=ksI-egarPnlxit0qKKjtjZ2L82qGLxqxZ6s92O0eBA4,1005
|
|
41
44
|
phoenix/metrics/README.md,sha256=5gekqTU-5gGdMwvcfNp2Wlu8p1ul9kGY_jq0XXQusoI,1964
|
|
42
45
|
phoenix/metrics/__init__.py,sha256=sLp7td1GIt_0Z8dPUyP4L0-_4x9c871yAaGX30oMsvg,2433
|
|
@@ -52,16 +55,17 @@ phoenix/pointcloud/pointcloud.py,sha256=ms-h1FLC0xXb3sk256zpSuZQDE2hdOAJzRNBklP0
|
|
|
52
55
|
phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
|
|
53
56
|
phoenix/pointcloud/umap_parameters.py,sha256=lJsEOrbSuSiqI7g4Yt6xj7kgYxEqoep4ZHWLr6VWBqw,1760
|
|
54
57
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
-
phoenix/server/app.py,sha256=
|
|
58
|
+
phoenix/server/app.py,sha256=ptm47TRYPj36fNiko8Ja2R40J8HQFlfspSRUIQ1by88,7239
|
|
56
59
|
phoenix/server/evaluation_handler.py,sha256=HzaoD8Cv9HbEdd0nYSTZoakKsE8Ic5lVjeuBh0vnhoA,1554
|
|
57
|
-
phoenix/server/main.py,sha256=
|
|
58
|
-
phoenix/server/span_handler.py,sha256=
|
|
60
|
+
phoenix/server/main.py,sha256=1puvebfgsD3GBHiMn5Dx-dURnby7iMGXK5Uce_KaQG4,6804
|
|
61
|
+
phoenix/server/span_handler.py,sha256=reYUDaN5bavSFjEiSfvYyAG_mpJs6S3iB-RNCkZrSUU,1295
|
|
59
62
|
phoenix/server/thread_server.py,sha256=a9Vnzc69ZLqJbI_FUSOY3eeuYCiCq6aprPj2gS_RB-M,2097
|
|
63
|
+
phoenix/server/trace_handler.py,sha256=pXanrp9L21Mh7MnyJbj202NJ-Rn4bCjG0oL4DtdKcls,2074
|
|
60
64
|
phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
65
|
phoenix/server/api/context.py,sha256=02vRgyLFpDCmh97QwsjWD5cdNZkoCUtDPPs1YItbdbI,583
|
|
62
66
|
phoenix/server/api/helpers.py,sha256=_V1eVkchZmTkhOfRC4QqR1sUB2xtIxdsMJkDouZq_IE,251
|
|
63
67
|
phoenix/server/api/interceptor.py,sha256=do_J4HjPPQ_C7bMmqe1YpTmt_hoxcwC2I8P3n5sZBo4,1302
|
|
64
|
-
phoenix/server/api/schema.py,sha256=
|
|
68
|
+
phoenix/server/api/schema.py,sha256=b_GiRJKkfnqR_Fy51N4NWN2nh7clao2V6C8G94nTYo4,15303
|
|
65
69
|
phoenix/server/api/input_types/ClusterInput.py,sha256=EL4ftvZxQ8mVdruUPcdhMhByORmSmM8S-X6RPqU6GX0,179
|
|
66
70
|
phoenix/server/api/input_types/Coordinates.py,sha256=meTwbIjwTfqx5DGD2DBlH9wQzdQVNM5a8x9dp1FfIgA,173
|
|
67
71
|
phoenix/server/api/input_types/DataQualityMetricInput.py,sha256=LazvmQCCM5m9SDZTpyxQXO1rYF4cmsc3lsR2S9S65X4,1292
|
|
@@ -121,19 +125,20 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
121
125
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
122
126
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
123
127
|
phoenix/server/static/index.css,sha256=KKGpx4iwF91VGRm0YN-4cn8oC-oIqC6HecoPf0x3ZM8,1885
|
|
124
|
-
phoenix/server/static/index.js,sha256=
|
|
128
|
+
phoenix/server/static/index.js,sha256=gP89MKs13uK-k9A_hQFQM6E03GPltzNoEFgaAHaAgBs,3257264
|
|
125
129
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
126
130
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
127
|
-
phoenix/server/templates/index.html,sha256=
|
|
131
|
+
phoenix/server/templates/index.html,sha256=_ZVGz2JYDgJjCL2kxSbVjN1qY7drKYerVIXNfmcW30k,1765
|
|
128
132
|
phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
129
133
|
phoenix/session/evaluation.py,sha256=88wSWlUi71RDHZksRE3hG91GHq8rMRYXirkyA3IbM8Y,4681
|
|
130
|
-
phoenix/session/session.py,sha256=
|
|
134
|
+
phoenix/session/session.py,sha256=WL0lUGnBp9ZJHOwkLPkf32QvmHOThC5VIERa4SP0o_E,17815
|
|
131
135
|
phoenix/trace/__init__.py,sha256=lnuxATMemAqjURYqOfIo_HyCo5oIWIVTy98XAsiS1d8,215
|
|
132
136
|
phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
|
|
133
|
-
phoenix/trace/exporter.py,sha256=
|
|
137
|
+
phoenix/trace/exporter.py,sha256=z3xrGJhIRh7XMy4Q1FkR3KmFZym-GX0XxLTZ6eSnN0Q,4347
|
|
134
138
|
phoenix/trace/fixtures.py,sha256=lFuhPe-di54BmCT-RxS95m3e2-z1YBOo8CxsqYSgDD8,6341
|
|
139
|
+
phoenix/trace/otel.py,sha256=4cJ85O_y_S6C_kkVvYh8d1d1mzKpGk_eQKjg688PI0k,13899
|
|
135
140
|
phoenix/trace/schemas.py,sha256=m1wVlYFT6qL3FovD3TtTYsEgN6OHvv52gNdJkoPCmuY,5400
|
|
136
|
-
phoenix/trace/semantic_conventions.py,sha256=
|
|
141
|
+
phoenix/trace/semantic_conventions.py,sha256=u6NG85ZhbreriZr8cqJaddldM_jUcew7JilszY7JUk8,4652
|
|
137
142
|
phoenix/trace/span_evaluations.py,sha256=9RTJ8BFhXDJNtqErWRlMj65FG7wJiI41YTgB7vYLqcY,8429
|
|
138
143
|
phoenix/trace/span_json_decoder.py,sha256=Xv-0uCsHgwzQb0dqTa7CuuDeXAPaXjQICyCFK3ZQaSs,3089
|
|
139
144
|
phoenix/trace/span_json_encoder.py,sha256=C5y7rkyOcV08oJC5t8TZqVxsKCZMJKad7bBQzAgLoDs,1763
|
|
@@ -147,24 +152,21 @@ phoenix/trace/dsl/missing.py,sha256=BWPOHr2_tBkPDgVeq8GVXXVbNbJiBelu4NtwHBg6mTE,
|
|
|
147
152
|
phoenix/trace/dsl/query.py,sha256=BAdL5rcliatBtxpcuZ86am5mmSUkhzCMF3PRSH8v3m8,9890
|
|
148
153
|
phoenix/trace/langchain/__init__.py,sha256=vAjrmrreetV7L5IL8VH_9efG9VJunJTgT0iKyWqjFbc,148
|
|
149
154
|
phoenix/trace/langchain/instrumentor.py,sha256=HkNKbFNclTYjRXBM8qU4qvZHdyw06J9bhwgE7JnqbNI,1323
|
|
150
|
-
phoenix/trace/langchain/tracer.py,sha256=
|
|
155
|
+
phoenix/trace/langchain/tracer.py,sha256=1Oz3orSDpZX1pZKwtZbeM_f9tiAhQb7Of8ARjRlKVQY,16827
|
|
151
156
|
phoenix/trace/llama_index/__init__.py,sha256=wCcQgD9CG5TA8i-1XsSed4ZzwHTUmqZwegQAV_FqEng,178
|
|
152
157
|
phoenix/trace/llama_index/callback.py,sha256=YW3qqzWZUEs9aiDx-2628Eae_rct_Yb-DDzT9dV_xiI,27061
|
|
153
158
|
phoenix/trace/llama_index/debug_callback.py,sha256=SKToD9q_QADSGTJ5lhilqRVKaUnUSRXUvURCzN4by2U,1367
|
|
154
159
|
phoenix/trace/llama_index/streaming.py,sha256=5cTtr8evvcEAB88Xb4ih3WEw0xAF4x5W9PehUX9l5_0,3258
|
|
155
160
|
phoenix/trace/openai/__init__.py,sha256=J3G0uqCxGdksUpaQVHds_Egv2drvh8UEqoLjiQAOveg,79
|
|
156
161
|
phoenix/trace/openai/instrumentor.py,sha256=H1T2_1uqeH2lKCKeMmirEUl6PRtHQlQTXfsLR_hwDFM,24948
|
|
157
|
-
phoenix/trace/v1/__init__.py,sha256
|
|
162
|
+
phoenix/trace/v1/__init__.py,sha256=-IbAD0ruESMjvQLvGAg9CTfjBUATFDx1OXseDPis6-0,88
|
|
158
163
|
phoenix/trace/v1/evaluation_pb2.py,sha256=8sXvv2BW_vqD30MOMbmkeE2zpmm7ncik21kl3e-HzeQ,2254
|
|
159
164
|
phoenix/trace/v1/evaluation_pb2.pyi,sha256=cCbbx06gwQmaH14s3J1X25TtaARh-k1abbxQdQCXGm8,4500
|
|
160
|
-
phoenix/trace/v1/trace_pb2.py,sha256=IfvVb4PkUS6W72uJvcZTj7yj8hFvaaRac0RiOYae7Ik,5724
|
|
161
|
-
phoenix/trace/v1/trace_pb2.pyi,sha256=4OErYEvVemBUoCiD2ABG9NSpGDEEzJkHr6x9ALYvE5Y,16497
|
|
162
|
-
phoenix/trace/v1/utils.py,sha256=j7gunL9CuSi7Xif56oWYGx0sc7KjfJhXzWcJia4ZM-8,17815
|
|
163
165
|
phoenix/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
164
166
|
phoenix/utilities/error_handling.py,sha256=7b5rpGFj9EWZ8yrZK1IHvxB89suWk3lggDayUQcvZds,1946
|
|
165
167
|
phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,222
|
|
166
|
-
arize_phoenix-2.
|
|
167
|
-
arize_phoenix-2.
|
|
168
|
-
arize_phoenix-2.
|
|
169
|
-
arize_phoenix-2.
|
|
170
|
-
arize_phoenix-2.
|
|
168
|
+
arize_phoenix-2.2.0rc0.dist-info/METADATA,sha256=cV0tw8Sq1yms7yncqdyAkIoUOMVBIfDQkS_X9wlmgKY,26482
|
|
169
|
+
arize_phoenix-2.2.0rc0.dist-info/WHEEL,sha256=mRYSEL3Ih6g5a_CVMIcwiF__0Ae4_gLYh01YFNwiq1k,87
|
|
170
|
+
arize_phoenix-2.2.0rc0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
171
|
+
arize_phoenix-2.2.0rc0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
172
|
+
arize_phoenix-2.2.0rc0.dist-info/RECORD,,
|
phoenix/__init__.py
CHANGED
|
@@ -5,8 +5,7 @@ from .session.evaluation import log_evaluations
|
|
|
5
5
|
from .session.session import NotebookEnvironment, Session, active_session, close_app, launch_app
|
|
6
6
|
from .trace.fixtures import load_example_traces
|
|
7
7
|
from .trace.trace_dataset import TraceDataset
|
|
8
|
-
|
|
9
|
-
__version__ = "2.0.0"
|
|
8
|
+
from .version import __version__
|
|
10
9
|
|
|
11
10
|
# module level doc-string
|
|
12
11
|
__doc__ = """
|
|
@@ -25,6 +24,7 @@ Here are just a few of the things that phoenix does well:
|
|
|
25
24
|
"""
|
|
26
25
|
|
|
27
26
|
__all__ = [
|
|
27
|
+
"__version__",
|
|
28
28
|
"Dataset",
|
|
29
29
|
"EmbeddingColumnNames",
|
|
30
30
|
"RetrievalEmbeddingColumnNames",
|
phoenix/core/evals.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import weakref
|
|
3
3
|
from collections import defaultdict
|
|
4
|
+
from datetime import datetime, timezone
|
|
4
5
|
from queue import SimpleQueue
|
|
5
6
|
from threading import RLock, Thread
|
|
6
7
|
from types import MethodType
|
|
@@ -46,6 +47,7 @@ class Evals:
|
|
|
46
47
|
self._document_evaluations_by_name: DefaultDict[
|
|
47
48
|
EvaluationName, DefaultDict[SpanID, Dict[DocumentPosition, pb.Evaluation]]
|
|
48
49
|
] = defaultdict(lambda: defaultdict(dict))
|
|
50
|
+
self._last_updated_at: Optional[datetime] = None
|
|
49
51
|
self._start_consumer()
|
|
50
52
|
|
|
51
53
|
def put(self, evaluation: pb.Evaluation) -> None:
|
|
@@ -92,10 +94,16 @@ class Evals:
|
|
|
92
94
|
)
|
|
93
95
|
else:
|
|
94
96
|
assert_never(subject_id_kind)
|
|
97
|
+
self._last_updated_at = datetime.now(timezone.utc)
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def last_updated_at(self) -> Optional[datetime]:
|
|
101
|
+
return self._last_updated_at
|
|
95
102
|
|
|
96
103
|
def get_span_evaluation(self, span_id: SpanID, name: str) -> Optional[pb.Evaluation]:
|
|
97
104
|
with self._lock:
|
|
98
|
-
|
|
105
|
+
span_evaluations = self._evaluations_by_span_id.get(span_id)
|
|
106
|
+
return span_evaluations.get(name) if span_evaluations else None
|
|
99
107
|
|
|
100
108
|
def get_span_evaluation_names(self) -> List[EvaluationName]:
|
|
101
109
|
with self._lock:
|
|
@@ -108,28 +116,36 @@ class Evals:
|
|
|
108
116
|
with self._lock:
|
|
109
117
|
if span_id is None:
|
|
110
118
|
return list(self._document_evaluations_by_name)
|
|
111
|
-
|
|
119
|
+
document_evaluations = self._document_evaluations_by_span_id.get(span_id)
|
|
120
|
+
return list(document_evaluations) if document_evaluations else []
|
|
112
121
|
|
|
113
122
|
def get_span_evaluation_labels(self, name: EvaluationName) -> Tuple[str, ...]:
|
|
114
123
|
with self._lock:
|
|
115
|
-
|
|
124
|
+
labels = self._span_evaluation_labels.get(name)
|
|
125
|
+
return tuple(labels) if labels else ()
|
|
116
126
|
|
|
117
127
|
def get_span_evaluation_span_ids(self, name: EvaluationName) -> Tuple[SpanID, ...]:
|
|
118
128
|
with self._lock:
|
|
119
|
-
|
|
129
|
+
span_evaluations = self._span_evaluations_by_name.get(name)
|
|
130
|
+
return tuple(span_evaluations.keys()) if span_evaluations else ()
|
|
120
131
|
|
|
121
132
|
def get_evaluations_by_span_id(self, span_id: SpanID) -> List[pb.Evaluation]:
|
|
122
133
|
with self._lock:
|
|
123
|
-
|
|
134
|
+
evaluations = self._evaluations_by_span_id.get(span_id)
|
|
135
|
+
return list(evaluations.values()) if evaluations else []
|
|
124
136
|
|
|
125
137
|
def get_document_evaluation_span_ids(self, name: EvaluationName) -> Tuple[SpanID, ...]:
|
|
126
138
|
with self._lock:
|
|
127
|
-
|
|
139
|
+
document_evaluations = self._document_evaluations_by_name.get(name)
|
|
140
|
+
return tuple(document_evaluations.keys()) if document_evaluations else ()
|
|
128
141
|
|
|
129
142
|
def get_document_evaluations_by_span_id(self, span_id: SpanID) -> List[pb.Evaluation]:
|
|
130
143
|
all_evaluations: List[pb.Evaluation] = []
|
|
131
144
|
with self._lock:
|
|
132
|
-
|
|
145
|
+
document_evaluations = self._document_evaluations_by_span_id.get(span_id)
|
|
146
|
+
if not document_evaluations:
|
|
147
|
+
return all_evaluations
|
|
148
|
+
for evaluations in document_evaluations.values():
|
|
133
149
|
all_evaluations.extend(evaluations.values())
|
|
134
150
|
return all_evaluations
|
|
135
151
|
|
|
@@ -144,7 +160,12 @@ class Evals:
|
|
|
144
160
|
# of one trillion, we would not want to create a result that large.
|
|
145
161
|
scores: List[float] = [np.nan] * num_documents
|
|
146
162
|
with self._lock:
|
|
147
|
-
|
|
163
|
+
document_evaluations = self._document_evaluations_by_span_id.get(span_id)
|
|
164
|
+
if not document_evaluations:
|
|
165
|
+
return scores
|
|
166
|
+
evaluations = document_evaluations.get(evaluation_name)
|
|
167
|
+
if not evaluations:
|
|
168
|
+
return scores
|
|
148
169
|
for document_position, evaluation in evaluations.items():
|
|
149
170
|
result = evaluation.result
|
|
150
171
|
if result.HasField("score") and document_position < num_documents:
|
phoenix/core/traces.py
CHANGED
|
@@ -13,20 +13,21 @@ from typing import (
|
|
|
13
13
|
Iterator,
|
|
14
14
|
List,
|
|
15
15
|
Optional,
|
|
16
|
+
Set,
|
|
16
17
|
SupportsFloat,
|
|
17
18
|
Tuple,
|
|
18
|
-
Union,
|
|
19
19
|
cast,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
+
import opentelemetry.proto.trace.v1.trace_pb2 as otlp
|
|
22
23
|
from ddsketch import DDSketch
|
|
23
24
|
from sortedcontainers import SortedKeyList
|
|
24
25
|
from typing_extensions import TypeAlias
|
|
25
26
|
from wrapt import ObjectProxy
|
|
26
27
|
|
|
27
|
-
import phoenix.trace.v1 as pb
|
|
28
28
|
from phoenix.datetime_utils import right_open_time_range
|
|
29
29
|
from phoenix.trace import semantic_conventions
|
|
30
|
+
from phoenix.trace.otel import decode
|
|
30
31
|
from phoenix.trace.schemas import (
|
|
31
32
|
ATTRIBUTE_PREFIX,
|
|
32
33
|
COMPUTED_PREFIX,
|
|
@@ -34,9 +35,10 @@ from phoenix.trace.schemas import (
|
|
|
34
35
|
Span,
|
|
35
36
|
SpanAttributes,
|
|
36
37
|
SpanID,
|
|
38
|
+
SpanStatusCode,
|
|
37
39
|
TraceID,
|
|
38
40
|
)
|
|
39
|
-
from phoenix.trace.
|
|
41
|
+
from phoenix.trace.semantic_conventions import RETRIEVAL_DOCUMENTS
|
|
40
42
|
|
|
41
43
|
END_OF_QUEUE = None # sentinel value for queue termination
|
|
42
44
|
|
|
@@ -74,15 +76,15 @@ class ReadableSpan(ObjectProxy): # type: ignore
|
|
|
74
76
|
are ingested, and would need to be re-computed on the fly.
|
|
75
77
|
"""
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def __init__(self, span: pb.Span) -> None:
|
|
79
|
+
def __init__(self, otlp_span: otlp.Span) -> None:
|
|
80
|
+
span = decode(otlp_span)
|
|
80
81
|
super().__init__(span)
|
|
82
|
+
self._self_otlp_span = otlp_span
|
|
81
83
|
self._self_computed_values: Dict[str, SupportsFloat] = {}
|
|
82
84
|
|
|
83
85
|
@property
|
|
84
86
|
def span(self) -> Span:
|
|
85
|
-
span = decode(self.
|
|
87
|
+
span = decode(self._self_otlp_span)
|
|
86
88
|
span.attributes.update(cast(SpanAttributes, self._self_computed_values))
|
|
87
89
|
# TODO: compute latency rank percent (which can change depending on how
|
|
88
90
|
# many spans already ingested).
|
|
@@ -96,9 +98,7 @@ class ReadableSpan(ObjectProxy): # type: ignore
|
|
|
96
98
|
return getattr(self.__wrapped__.context, suffix_key, None)
|
|
97
99
|
if key.startswith(ATTRIBUTE_PREFIX):
|
|
98
100
|
suffix_key = key[len(ATTRIBUTE_PREFIX) :]
|
|
99
|
-
|
|
100
|
-
return None
|
|
101
|
-
return self.__wrapped__.attributes[suffix_key]
|
|
101
|
+
return self.__wrapped__.attributes.get(suffix_key)
|
|
102
102
|
return getattr(self.__wrapped__, key, None)
|
|
103
103
|
|
|
104
104
|
def __setitem__(self, key: str, value: Any) -> None:
|
|
@@ -113,21 +113,21 @@ ChildSpanID: TypeAlias = SpanID
|
|
|
113
113
|
|
|
114
114
|
class Traces:
|
|
115
115
|
def __init__(self) -> None:
|
|
116
|
-
self._queue: "SimpleQueue[Optional[
|
|
116
|
+
self._queue: "SimpleQueue[Optional[otlp.Span]]" = SimpleQueue()
|
|
117
117
|
# Putting `None` as the sentinel value for queue termination.
|
|
118
118
|
weakref.finalize(self, self._queue.put, END_OF_QUEUE)
|
|
119
119
|
self._lock = RLock()
|
|
120
120
|
self._spans: Dict[SpanID, ReadableSpan] = {}
|
|
121
121
|
self._parent_span_ids: Dict[SpanID, ParentSpanID] = {}
|
|
122
|
-
self._traces:
|
|
123
|
-
self._child_span_ids: DefaultDict[SpanID,
|
|
124
|
-
self._orphan_spans: DefaultDict[ParentSpanID, List[
|
|
122
|
+
self._traces: DefaultDict[TraceID, List[SpanID]] = defaultdict(list)
|
|
123
|
+
self._child_span_ids: DefaultDict[SpanID, Set[ChildSpanID]] = defaultdict(set)
|
|
124
|
+
self._orphan_spans: DefaultDict[ParentSpanID, List[otlp.Span]] = defaultdict(list)
|
|
125
125
|
self._num_documents: DefaultDict[SpanID, int] = defaultdict(int)
|
|
126
126
|
self._start_time_sorted_span_ids: SortedKeyList[SpanID] = SortedKeyList(
|
|
127
|
-
key=lambda span_id: self._spans[span_id].start_time
|
|
127
|
+
key=lambda span_id: self._spans[span_id].start_time,
|
|
128
128
|
)
|
|
129
129
|
self._start_time_sorted_root_span_ids: SortedKeyList[SpanID] = SortedKeyList(
|
|
130
|
-
key=lambda span_id: self._spans[span_id].start_time
|
|
130
|
+
key=lambda span_id: self._spans[span_id].start_time,
|
|
131
131
|
)
|
|
132
132
|
self._latency_sorted_root_span_ids: SortedKeyList[SpanID] = SortedKeyList(
|
|
133
133
|
key=lambda span_id: self._spans[span_id][ComputedAttributes.LATENCY_MS.value],
|
|
@@ -136,15 +136,18 @@ class Traces:
|
|
|
136
136
|
self._min_start_time: Optional[datetime] = None
|
|
137
137
|
self._max_start_time: Optional[datetime] = None
|
|
138
138
|
self._token_count_total: int = 0
|
|
139
|
+
self._last_updated_at: Optional[datetime] = None
|
|
139
140
|
self._start_consumer()
|
|
140
141
|
|
|
141
|
-
def put(self, span: Optional[
|
|
142
|
-
self._queue.put(
|
|
142
|
+
def put(self, span: Optional[otlp.Span] = None) -> None:
|
|
143
|
+
self._queue.put(span)
|
|
143
144
|
|
|
144
145
|
def get_trace(self, trace_id: TraceID) -> Iterator[Span]:
|
|
145
146
|
with self._lock:
|
|
146
147
|
# make a copy because source data can mutate during iteration
|
|
147
|
-
|
|
148
|
+
if not (trace := self._traces.get(trace_id)):
|
|
149
|
+
return
|
|
150
|
+
span_ids = tuple(trace)
|
|
148
151
|
for span_id in span_ids:
|
|
149
152
|
if span := self[span_id]:
|
|
150
153
|
yield span
|
|
@@ -194,7 +197,7 @@ class Traces:
|
|
|
194
197
|
|
|
195
198
|
def get_num_documents(self, span_id: SpanID) -> int:
|
|
196
199
|
with self._lock:
|
|
197
|
-
return self._num_documents
|
|
200
|
+
return self._num_documents.get(span_id) or 0
|
|
198
201
|
|
|
199
202
|
def latency_rank_percent(self, latency_ms: float) -> Optional[float]:
|
|
200
203
|
"""
|
|
@@ -221,11 +224,17 @@ class Traces:
|
|
|
221
224
|
def get_descendant_span_ids(self, span_id: SpanID) -> Iterator[SpanID]:
|
|
222
225
|
with self._lock:
|
|
223
226
|
# make a copy because source data can mutate during iteration
|
|
224
|
-
|
|
227
|
+
if not (child_span_ids := self._child_span_ids.get(span_id)):
|
|
228
|
+
return
|
|
229
|
+
span_ids = tuple(child_span_ids)
|
|
225
230
|
for child_span_id in span_ids:
|
|
226
231
|
yield child_span_id
|
|
227
232
|
yield from self.get_descendant_span_ids(child_span_id)
|
|
228
233
|
|
|
234
|
+
@property
|
|
235
|
+
def last_updated_at(self) -> Optional[datetime]:
|
|
236
|
+
return self._last_updated_at
|
|
237
|
+
|
|
229
238
|
@property
|
|
230
239
|
def span_count(self) -> int:
|
|
231
240
|
"""Total number of spans (excluding orphan spans if any)"""
|
|
@@ -259,24 +268,24 @@ class Traces:
|
|
|
259
268
|
with self._lock:
|
|
260
269
|
self._process_span(item)
|
|
261
270
|
|
|
262
|
-
def _process_span(self, span:
|
|
263
|
-
|
|
271
|
+
def _process_span(self, span: otlp.Span) -> None:
|
|
272
|
+
new_span = ReadableSpan(span)
|
|
273
|
+
span_id = new_span.context.span_id
|
|
264
274
|
existing_span = self._spans.get(span_id)
|
|
265
|
-
if existing_span and existing_span.
|
|
275
|
+
if existing_span and existing_span.end_time:
|
|
266
276
|
# Reject updates if span has ended.
|
|
267
277
|
return
|
|
268
|
-
is_root_span = not
|
|
278
|
+
is_root_span = not new_span.parent_id
|
|
269
279
|
if not is_root_span:
|
|
270
|
-
parent_span_id =
|
|
280
|
+
parent_span_id = new_span.parent_id
|
|
271
281
|
if parent_span_id not in self._spans:
|
|
272
282
|
# Span can't be processed before its parent.
|
|
273
283
|
self._orphan_spans[parent_span_id].append(span)
|
|
274
284
|
return
|
|
275
|
-
self._child_span_ids[parent_span_id].
|
|
285
|
+
self._child_span_ids[parent_span_id].add(span_id)
|
|
276
286
|
self._parent_span_ids[span_id] = parent_span_id
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
end_time = span.end_time.ToDatetime(timezone.utc) if span.HasField("end_time") else None
|
|
287
|
+
start_time = new_span.start_time
|
|
288
|
+
end_time = new_span.end_time
|
|
280
289
|
if end_time:
|
|
281
290
|
new_span[ComputedAttributes.LATENCY_MS.value] = latency = (
|
|
282
291
|
end_time - start_time
|
|
@@ -287,7 +296,7 @@ class Traces:
|
|
|
287
296
|
if is_root_span and end_time:
|
|
288
297
|
self._latency_sorted_root_span_ids.add(span_id)
|
|
289
298
|
if not existing_span:
|
|
290
|
-
trace_id =
|
|
299
|
+
trace_id = new_span.context.trace_id
|
|
291
300
|
self._traces[trace_id].append(span_id)
|
|
292
301
|
if is_root_span:
|
|
293
302
|
self._start_time_sorted_root_span_ids.add(span_id)
|
|
@@ -303,7 +312,7 @@ class Traces:
|
|
|
303
312
|
else max(self._max_start_time, start_time)
|
|
304
313
|
)
|
|
305
314
|
new_span[ComputedAttributes.ERROR_COUNT.value] = int(
|
|
306
|
-
|
|
315
|
+
new_span.status_code is SpanStatusCode.ERROR
|
|
307
316
|
)
|
|
308
317
|
# Update cumulative values for span's ancestors.
|
|
309
318
|
for attribute_name, cumulative_attribute_name in (
|
|
@@ -336,14 +345,16 @@ class Traces:
|
|
|
336
345
|
self._token_count_total -= existing_span[LLM_TOKEN_COUNT_TOTAL] or 0
|
|
337
346
|
self._token_count_total += new_span[LLM_TOKEN_COUNT_TOTAL] or 0
|
|
338
347
|
# Update number of documents
|
|
339
|
-
num_documents_update = len(
|
|
348
|
+
num_documents_update = len(new_span.attributes.get(RETRIEVAL_DOCUMENTS) or ())
|
|
340
349
|
if existing_span:
|
|
341
|
-
num_documents_update -= len(existing_span.
|
|
350
|
+
num_documents_update -= len(existing_span.attributes.get(RETRIEVAL_DOCUMENTS) or ())
|
|
342
351
|
if num_documents_update:
|
|
343
352
|
self._num_documents[span_id] += num_documents_update
|
|
344
353
|
# Process previously orphaned spans, if any.
|
|
345
354
|
for orphan_span in self._orphan_spans.pop(span_id, ()):
|
|
346
355
|
self._process_span(orphan_span)
|
|
356
|
+
# Update last updated timestamp
|
|
357
|
+
self._last_updated_at = datetime.now(timezone.utc)
|
|
347
358
|
|
|
348
359
|
def _add_value_to_span_ancestors(
|
|
349
360
|
self,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .evaluators import LLMEvaluator
|
|
1
|
+
from .evaluators import InvalidEvalCriteriaError, LLMEvaluator
|
|
2
2
|
from .functions import llm_classify, llm_generate, run_relevance_eval
|
|
3
3
|
from .models import BedrockModel, LiteLLMModel, OpenAIModel, VertexAIModel
|
|
4
4
|
from .retrievals import compute_precisions_at_k
|
|
@@ -16,11 +16,13 @@ from .templates import (
|
|
|
16
16
|
TOXICITY_PROMPT_RAILS_MAP,
|
|
17
17
|
TOXICITY_PROMPT_TEMPLATE,
|
|
18
18
|
ClassificationTemplate,
|
|
19
|
+
EvalCriteria,
|
|
19
20
|
PromptTemplate,
|
|
20
21
|
)
|
|
21
22
|
from .utils import NOT_PARSABLE, download_benchmark_dataset
|
|
22
23
|
|
|
23
24
|
__all__ = [
|
|
25
|
+
"EvalCriteria",
|
|
24
26
|
"compute_precisions_at_k",
|
|
25
27
|
"download_benchmark_dataset",
|
|
26
28
|
"llm_classify",
|
|
@@ -46,4 +48,5 @@ __all__ = [
|
|
|
46
48
|
"QA_PROMPT_TEMPLATE",
|
|
47
49
|
"NOT_PARSABLE",
|
|
48
50
|
"run_relevance_eval",
|
|
51
|
+
"InvalidEvalCriteriaError",
|
|
49
52
|
]
|