arize-phoenix 11.28.0__py3-none-any.whl → 11.30.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.
- {arize_phoenix-11.28.0.dist-info → arize_phoenix-11.30.0.dist-info}/METADATA +3 -2
- {arize_phoenix-11.28.0.dist-info → arize_phoenix-11.30.0.dist-info}/RECORD +23 -22
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +17 -24
- phoenix/server/api/dataloaders/document_evaluations.py +3 -3
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +88 -34
- phoenix/server/api/dataloaders/experiment_error_rates.py +21 -28
- phoenix/server/api/routers/v1/__init__.py +2 -0
- phoenix/server/api/routers/v1/documents.py +175 -0
- phoenix/server/api/routers/v1/spans.py +5 -3
- phoenix/server/api/routers/v1/traces.py +5 -3
- phoenix/server/api/types/Dataset.py +69 -21
- phoenix/server/api/types/Evaluation.py +5 -4
- phoenix/server/api/types/Experiment.py +4 -5
- phoenix/server/api/types/Span.py +2 -2
- phoenix/server/static/.vite/manifest.json +9 -9
- phoenix/server/static/assets/{components-C3HQDu_r.js → components-BBwXqJXQ.js} +4 -3
- phoenix/server/static/assets/{index-C-sjZRYC.js → index-C_gU3x10.js} +1 -1
- phoenix/server/static/assets/{pages-DvrxSPg3.js → pages-YmQb55Uo.js} +399 -392
- phoenix/version.py +1 -1
- {arize_phoenix-11.28.0.dist-info → arize_phoenix-11.30.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-11.28.0.dist-info → arize_phoenix-11.30.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-11.28.0.dist-info → arize_phoenix-11.30.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-11.28.0.dist-info → arize_phoenix-11.30.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.
|
|
3
|
+
Version: 11.30.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
|
|
@@ -50,7 +50,8 @@ Requires-Dist: python-multipart
|
|
|
50
50
|
Requires-Dist: scikit-learn
|
|
51
51
|
Requires-Dist: scipy
|
|
52
52
|
Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
|
|
53
|
-
Requires-Dist: sqlean-py
|
|
53
|
+
Requires-Dist: sqlean-py<3.50,>=3.45.1; platform_system == 'Windows'
|
|
54
|
+
Requires-Dist: sqlean-py>=3.45.1; platform_system != 'Windows'
|
|
54
55
|
Requires-Dist: starlette
|
|
55
56
|
Requires-Dist: strawberry-graphql==0.270.1
|
|
56
57
|
Requires-Dist: tqdm
|
|
@@ -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=
|
|
9
|
+
phoenix/version.py,sha256=JHzYn5SQjWvqEZWixlgmU5X8oFvAzqJf2SdpbNxVVK4,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
|
|
@@ -120,14 +120,14 @@ phoenix/server/api/utils.py,sha256=quCBRcusc6PUq9tJq7M8PgwFZp7nXgVAxtbw8feribY,8
|
|
|
120
120
|
phoenix/server/api/dataloaders/__init__.py,sha256=ddiX1BdbyGkPTzMZNo-hkF_2kqIquelBUFvQejnAJYk,6834
|
|
121
121
|
phoenix/server/api/dataloaders/annotation_configs_by_project.py,sha256=_Nfiug9o01JimU3Z0LpZJ0uaMCjchXomyt_dYAxPFRY,1178
|
|
122
122
|
phoenix/server/api/dataloaders/annotation_summaries.py,sha256=0b23-bucBKyL25RWb2QzCNJjQzrq403qMmHKUVD5W4M,14377
|
|
123
|
-
phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=
|
|
123
|
+
phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=_wEcC47zOtLFMYTfyaFWA93TlAVC3kAPZhMnRO-xB24,1809
|
|
124
124
|
phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=xF7M2dg3UmjhdCrscnztCIBBI0cg3RF48IIqvilpc18,4623
|
|
125
125
|
phoenix/server/api/dataloaders/dataset_example_spans.py,sha256=z_MFquqAcJ9wat7BBp7MVeJ9BYuu2EZEdaog52iWDno,1390
|
|
126
126
|
phoenix/server/api/dataloaders/document_evaluation_summaries.py,sha256=9fdROnzp-mymggHwNvpRkCk93LUFxxLy55-j3HP_2HY,5565
|
|
127
|
-
phoenix/server/api/dataloaders/document_evaluations.py,sha256=
|
|
127
|
+
phoenix/server/api/dataloaders/document_evaluations.py,sha256=W1b7TIlmPG61vR7kEcLZ5hAQYfkSKZAgrJOXYkA9-Ko,1246
|
|
128
128
|
phoenix/server/api/dataloaders/document_retrieval_metrics.py,sha256=37EcAW7oYQuWYHMDHb0wcqbWj9lhSskvzDO7NJbT5Js,4136
|
|
129
|
-
phoenix/server/api/dataloaders/experiment_annotation_summaries.py,sha256=
|
|
130
|
-
phoenix/server/api/dataloaders/experiment_error_rates.py,sha256=
|
|
129
|
+
phoenix/server/api/dataloaders/experiment_annotation_summaries.py,sha256=CFVj7DwFYj330FLU5w3zEr12AGUX1e8ZX0X5buxMuEk,5643
|
|
130
|
+
phoenix/server/api/dataloaders/experiment_error_rates.py,sha256=06IZF07qt2y167DBM49QkSNdnphPArhcsgYFcunaL-U,1992
|
|
131
131
|
phoenix/server/api/dataloaders/experiment_run_annotations.py,sha256=uJ--9Ue4tnmZYH9Zy-Cj2Y2t3xzs2xUqN8Y6EGe1MCo,1296
|
|
132
132
|
phoenix/server/api/dataloaders/experiment_run_counts.py,sha256=j_7229IL705p_TycxIMYylhSgLHsAn91TiGPYXtOuQ8,1617
|
|
133
133
|
phoenix/server/api/dataloaders/experiment_sequence_number.py,sha256=zM_f78fnqhppLtevrx9iISQSN7w_BNeXT9CoX8jYgAI,1534
|
|
@@ -255,10 +255,11 @@ phoenix/server/api/routers/auth.py,sha256=PKGwWdw7O015KmjMY1mIxlvXeU7OrmqIPF5TWT
|
|
|
255
255
|
phoenix/server/api/routers/embeddings.py,sha256=BpZGJee0pdL0W5Rp1L0b30dEtZTgJeVqXky8LgZ0ZXw,898
|
|
256
256
|
phoenix/server/api/routers/oauth2.py,sha256=rPcKFvfijzBYLjfwbCNzCn0ihn4wGWh4xh6BRqg9Ay4,24524
|
|
257
257
|
phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
|
|
258
|
-
phoenix/server/api/routers/v1/__init__.py,sha256=
|
|
258
|
+
phoenix/server/api/routers/v1/__init__.py,sha256=_CxVCs26dPuC2KygV3VzYqmoAECeFwiSTava9mxIJTE,2790
|
|
259
259
|
phoenix/server/api/routers/v1/annotation_configs.py,sha256=xp5lJmKYlRsINCUrRD9-lTAElw2v4hdFndS5BWrxICA,16048
|
|
260
260
|
phoenix/server/api/routers/v1/annotations.py,sha256=fVl2qeh_ZbWXGvFBTZgeL7aGkkINIScdjuyxnOoSzNM,6817
|
|
261
261
|
phoenix/server/api/routers/v1/datasets.py,sha256=9iPORLmbOrPKgUUcRDMs6ZczSIz7hvc6bngJy3IbdR0,38331
|
|
262
|
+
phoenix/server/api/routers/v1/documents.py,sha256=D8Pg6lEBHzSuPEDVts__X0ArIKBdQs_3gtIgoZXk_eU,6930
|
|
262
263
|
phoenix/server/api/routers/v1/evaluations.py,sha256=aBrPO-xCAWyTxydaHq7W2wQFm65k89uVR-H3VWsd6WQ,13062
|
|
263
264
|
phoenix/server/api/routers/v1/experiment_evaluations.py,sha256=DZ3UK9OoYKElpRcEER7559-KiAqWr-1IXpZ27FbfP3k,5249
|
|
264
265
|
phoenix/server/api/routers/v1/experiment_runs.py,sha256=LZeCQWQIEOZ9jK5Gp_C4JbiYY6AmnnWe85cVcvdkCLE,7107
|
|
@@ -266,8 +267,8 @@ phoenix/server/api/routers/v1/experiments.py,sha256=hIBecGACzGZEgl93ap_JV52pUv-I
|
|
|
266
267
|
phoenix/server/api/routers/v1/models.py,sha256=p3gJN-9SWiUYTUTft4bZMsZVCBNTb4nN1Foy68eRZzQ,1997
|
|
267
268
|
phoenix/server/api/routers/v1/projects.py,sha256=XR6uJxHXXtC1q8LNyS9W6iaj440sv1OKCu-OSBfxEys,12824
|
|
268
269
|
phoenix/server/api/routers/v1/prompts.py,sha256=chRYcLkOYDJdJfVZVukVTUyIRnLPvsJCg41CuPxOIU8,26695
|
|
269
|
-
phoenix/server/api/routers/v1/spans.py,sha256=
|
|
270
|
-
phoenix/server/api/routers/v1/traces.py,sha256=
|
|
270
|
+
phoenix/server/api/routers/v1/spans.py,sha256=6wu8nUQNp9ma_k5XGvcVx3fq5xPuaN5sbv15ouBWcVc,49438
|
|
271
|
+
phoenix/server/api/routers/v1/traces.py,sha256=ur4qVh8NDHDfwXKUNlAQoZhe4xAWe1Dv2ODixR5qroE,11418
|
|
271
272
|
phoenix/server/api/routers/v1/users.py,sha256=eO8zMtGU33Td2_G1l9D7Z0a4CG1CwBUCj_Z9z2uk7wg,12089
|
|
272
273
|
phoenix/server/api/routers/v1/utils.py,sha256=oXIOGPzPTkE0ZWUTRCoRIQQ7wTzoSwtWFaUSjlGBqts,4960
|
|
273
274
|
phoenix/server/api/types/Annotation.py,sha256=gsl8CwjIbDUbZRj4d9USwZ_w_Tkz4i7zuZh9ftV80jA,1132
|
|
@@ -284,7 +285,7 @@ phoenix/server/api/types/CostBreakdown.py,sha256=yw9dlb0blGIB_dWNP8yEvDHJztHjpiV
|
|
|
284
285
|
phoenix/server/api/types/CreateDatasetPayload.py,sha256=R-6zCmuD0f76RU9Giu78xwTHlASQs6Aq8yzvX1Kxc3g,140
|
|
285
286
|
phoenix/server/api/types/CronExpression.py,sha256=R7oxuSSX_eTUHQWaoaSueQqWDmkkHr5dBKRN6q-6ROk,331
|
|
286
287
|
phoenix/server/api/types/DataQualityMetric.py,sha256=Aieg3bHeBFaAf4mqeRcH1zT04sXAtQD8ATSHJt7FaBQ,1538
|
|
287
|
-
phoenix/server/api/types/Dataset.py,sha256=
|
|
288
|
+
phoenix/server/api/types/Dataset.py,sha256=23dst_glr7kFNC62-q6D9H2hJgrfZnGe7V-Bg72SJgg,15303
|
|
288
289
|
phoenix/server/api/types/DatasetExample.py,sha256=_9byxGpXfYb-hmFMUJeG7Bw1wsRKSJaHwF2IPAbFpFw,3115
|
|
289
290
|
phoenix/server/api/types/DatasetExampleRevision.py,sha256=c-jWR6dTguEZTm54IMlFr0Ic84I3nefyDnZb7nF5hnI,874
|
|
290
291
|
phoenix/server/api/types/DatasetValues.py,sha256=7VbCOLlzOXpZN80-zYF2UGuafRcPsZF-8WQNc0YsKFc,1119
|
|
@@ -298,12 +299,12 @@ phoenix/server/api/types/DocumentEvaluationSummary.py,sha256=dx4Btlfw9_XsfmibjfW
|
|
|
298
299
|
phoenix/server/api/types/DocumentRetrievalMetrics.py,sha256=amkpC3H5IU5-9GvO0telpbq00m6lIcv_2v446OpwFwc,1822
|
|
299
300
|
phoenix/server/api/types/EmbeddingDimension.py,sha256=AYvpZ1nWINAgN4BAZsA_xI_2TNFK6h5jmqzvkPs651M,19428
|
|
300
301
|
phoenix/server/api/types/EmbeddingMetadata.py,sha256=fJvNNYCbkf3SJalArLy9rcBq9Uj1SNac60zjqe1PFnM,461
|
|
301
|
-
phoenix/server/api/types/Evaluation.py,sha256=
|
|
302
|
+
phoenix/server/api/types/Evaluation.py,sha256=qkMmq5G9pgwUNOPSTRwR-nNAoqLT3LlXrq7O8cAgXQ8,1356
|
|
302
303
|
phoenix/server/api/types/EvaluationSummary.py,sha256=vILYejnfPvMwWEXOwhQZsANvYe3AdO2OkMR2rcgp1H4,1512
|
|
303
304
|
phoenix/server/api/types/Event.py,sha256=iYt_Jx1Roioo0vZ0iPeJTHcTu6NSm4ilVMJ-IMUHAKk,3970
|
|
304
305
|
phoenix/server/api/types/EventMetadata.py,sha256=-J0tYF9eZTHwCjwxQHY7Gckr2_MNW5OoWT1mydweZNM,635
|
|
305
306
|
phoenix/server/api/types/ExampleRevisionInterface.py,sha256=gV3Gt9-3Oi5wjaVtepC6nOt3FzTzZFD1KebNnqiw56E,294
|
|
306
|
-
phoenix/server/api/types/Experiment.py,sha256=
|
|
307
|
+
phoenix/server/api/types/Experiment.py,sha256=ifymI5SGqotIo01yAx-AsUONLzvFvjAKEU8gKi2WOzA,7700
|
|
307
308
|
phoenix/server/api/types/ExperimentAnnotationSummary.py,sha256=Uk3JtxIrsMoZT5tqc4nJdUOM3XegVzjUyoV3pkjNotE,256
|
|
308
309
|
phoenix/server/api/types/ExperimentComparison.py,sha256=PXFcB0e8aaJ391yRsuRJr9_dvTZI1RAzF93oC_-HtxU,461
|
|
309
310
|
phoenix/server/api/types/ExperimentRun.py,sha256=_fcwDLuURV0yviOlkjWAgJJwcCPdz-xGR6VX3UKf73s,6541
|
|
@@ -337,7 +338,7 @@ phoenix/server/api/types/ScalarDriftMetricEnum.py,sha256=IUAcRPpgL41WdoIgK6cNk2T
|
|
|
337
338
|
phoenix/server/api/types/Segments.py,sha256=vT2v0efoa5cuBKxLtxTnsUP5YJJCZfTloM71Spu0tMI,2915
|
|
338
339
|
phoenix/server/api/types/ServerStatus.py,sha256=t92OHuVhK9DXDk2vsBuHceQNKqYGpHwUp8DNGKz2wOk,88
|
|
339
340
|
phoenix/server/api/types/SortDir.py,sha256=OUpXhlCzCxPoXSDkJJygEs9Rw9pMymfaZUG5zPTrw4Y,152
|
|
340
|
-
phoenix/server/api/types/Span.py,sha256=
|
|
341
|
+
phoenix/server/api/types/Span.py,sha256=ag5qWOEbWDCNUAkSUd0K3biE_PuGT2oweL4gVKElNis,32000
|
|
341
342
|
phoenix/server/api/types/SpanAnnotation.py,sha256=uPWu7Z8rmpfKhaaxbged4_o00pPCR3nkn7Gji9vB8jY,1959
|
|
342
343
|
phoenix/server/api/types/SpanCostDetailSummaryEntry.py,sha256=RXAdOC6MFyR9mwaoj8lMMdI3_9r3z6mR2izJvlsj12U,252
|
|
343
344
|
phoenix/server/api/types/SpanCostSummary.py,sha256=wo03FCMcFzB5m4P5kvA5jzi9ACLbht38ozQbDJUh94g,357
|
|
@@ -392,10 +393,10 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
|
|
|
392
393
|
phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
|
|
393
394
|
phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
|
|
394
395
|
phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
|
|
395
|
-
phoenix/server/static/.vite/manifest.json,sha256=
|
|
396
|
-
phoenix/server/static/assets/components-
|
|
397
|
-
phoenix/server/static/assets/index-
|
|
398
|
-
phoenix/server/static/assets/pages-
|
|
396
|
+
phoenix/server/static/.vite/manifest.json,sha256=podIkdilPnaQGOQjbnF7zpOylgP4MXrSImpB5UGvNBc,2328
|
|
397
|
+
phoenix/server/static/assets/components-BBwXqJXQ.js,sha256=U8GMAX0TEjXRzhmqCMXjnVaQ9trJDICWTq9IcjqcNhE,664533
|
|
398
|
+
phoenix/server/static/assets/index-C_gU3x10.js,sha256=ouZyJslt5vOJGBHCHiO0ziM9Y5lTwAdB86lGFUbr-Ec,63396
|
|
399
|
+
phoenix/server/static/assets/pages-YmQb55Uo.js,sha256=tPGWJ9VTxJJSVoyQj_7VutaInS_SuhuXSal0nuJQTKQ,1269456
|
|
399
400
|
phoenix/server/static/assets/vendor-CqDb5u4o.css,sha256=zIyFiNJKxMaQk8AvtLgt1rR01oO10d1MFndSDKH9Clw,5517
|
|
400
401
|
phoenix/server/static/assets/vendor-RdRDaQiR.js,sha256=oTxLetZZXJ20yoKNAYExto9V73y8X5zjddWV46K9CWM,2595492
|
|
401
402
|
phoenix/server/static/assets/vendor-arizeai-DsYDNOqt.js,sha256=0HIkPJXbKTh85nqphdAXYeStRzdaim0IQxRXiXxa21U,121514
|
|
@@ -442,9 +443,9 @@ phoenix/utilities/project.py,sha256=auVpARXkDb-JgeX5f2aStyFIkeKvGwN9l7qrFeJMVxI,
|
|
|
442
443
|
phoenix/utilities/re.py,sha256=6YyUWIkv0zc2SigsxfOWIHzdpjKA_TZo2iqKq7zJKvw,2081
|
|
443
444
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
444
445
|
phoenix/utilities/template_formatters.py,sha256=gh9PJD6WEGw7TEYXfSst1UR4pWWwmjxMLrDVQ_CkpkQ,2779
|
|
445
|
-
arize_phoenix-11.
|
|
446
|
-
arize_phoenix-11.
|
|
447
|
-
arize_phoenix-11.
|
|
448
|
-
arize_phoenix-11.
|
|
449
|
-
arize_phoenix-11.
|
|
450
|
-
arize_phoenix-11.
|
|
446
|
+
arize_phoenix-11.30.0.dist-info/METADATA,sha256=p2LDUgcsaZ4l5qRVqP5FVFjrpVpZTvzTN60j913wTtM,31733
|
|
447
|
+
arize_phoenix-11.30.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
448
|
+
arize_phoenix-11.30.0.dist-info/entry_points.txt,sha256=Pgpn8Upxx9P8z8joPXZWl2LlnAlGc3gcQoVchb06X1Q,94
|
|
449
|
+
arize_phoenix-11.30.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
450
|
+
arize_phoenix-11.30.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
451
|
+
arize_phoenix-11.30.0.dist-info/RECORD,,
|
|
@@ -23,32 +23,25 @@ class AverageExperimentRunLatencyDataLoader(DataLoader[Key, Result]):
|
|
|
23
23
|
|
|
24
24
|
async def _load_fn(self, keys: list[Key]) -> list[Result]:
|
|
25
25
|
experiment_ids = keys
|
|
26
|
-
|
|
27
|
-
select(models.Experiment.id)
|
|
28
|
-
.where(models.Experiment.id.in_(set(experiment_ids)))
|
|
29
|
-
.subquery()
|
|
30
|
-
)
|
|
31
|
-
query = (
|
|
26
|
+
average_repetition_latency_ms = (
|
|
32
27
|
select(
|
|
33
|
-
|
|
34
|
-
func.avg(
|
|
35
|
-
func.extract("epoch", models.ExperimentRun.end_time)
|
|
36
|
-
- func.extract("epoch", models.ExperimentRun.start_time)
|
|
37
|
-
),
|
|
28
|
+
models.ExperimentRun.experiment_id.label("experiment_id"),
|
|
29
|
+
func.avg(models.ExperimentRun.latency_ms).label("average_repetition_latency_ms"),
|
|
38
30
|
)
|
|
39
|
-
.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
.group_by(resolved_experiment_ids.c.id)
|
|
31
|
+
.select_from(models.ExperimentRun)
|
|
32
|
+
.where(models.ExperimentRun.experiment_id.in_(experiment_ids))
|
|
33
|
+
.group_by(models.ExperimentRun.dataset_example_id, models.ExperimentRun.experiment_id)
|
|
34
|
+
.subquery()
|
|
45
35
|
)
|
|
36
|
+
query = select(
|
|
37
|
+
average_repetition_latency_ms.c.experiment_id,
|
|
38
|
+
func.avg(average_repetition_latency_ms.c.average_repetition_latency_ms).label(
|
|
39
|
+
"average_run_latency_ms"
|
|
40
|
+
),
|
|
41
|
+
).group_by(average_repetition_latency_ms.c.experiment_id)
|
|
46
42
|
async with self._db() as session:
|
|
47
|
-
|
|
48
|
-
experiment_id:
|
|
49
|
-
async for experiment_id,
|
|
43
|
+
average_run_latencies_ms = {
|
|
44
|
+
experiment_id: average_run_latency_ms
|
|
45
|
+
async for experiment_id, average_run_latency_ms in await session.stream(query)
|
|
50
46
|
}
|
|
51
|
-
return [
|
|
52
|
-
avg_latencies.get(experiment_id, ValueError(f"Unknown experiment: {experiment_id}"))
|
|
53
|
-
for experiment_id in keys
|
|
54
|
-
]
|
|
47
|
+
return [average_run_latencies_ms.get(experiment_id) for experiment_id in keys]
|
|
@@ -5,11 +5,11 @@ from strawberry.dataloader import DataLoader
|
|
|
5
5
|
from typing_extensions import TypeAlias
|
|
6
6
|
|
|
7
7
|
from phoenix.db import models
|
|
8
|
-
from phoenix.server.api.types.Evaluation import
|
|
8
|
+
from phoenix.server.api.types.Evaluation import DocumentAnnotation
|
|
9
9
|
from phoenix.server.types import DbSessionFactory
|
|
10
10
|
|
|
11
11
|
Key: TypeAlias = int
|
|
12
|
-
Result: TypeAlias = list[
|
|
12
|
+
Result: TypeAlias = list[DocumentAnnotation]
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class DocumentEvaluationsDataLoader(DataLoader[Key, Result]):
|
|
@@ -26,6 +26,6 @@ class DocumentEvaluationsDataLoader(DataLoader[Key, Result]):
|
|
|
26
26
|
)
|
|
27
27
|
async for document_evaluation in data:
|
|
28
28
|
document_evaluations_by_id[document_evaluation.span_rowid].append(
|
|
29
|
-
|
|
29
|
+
DocumentAnnotation.from_sql_document_annotation(document_evaluation)
|
|
30
30
|
)
|
|
31
31
|
return [document_evaluations_by_id[key] for key in keys]
|
|
@@ -2,7 +2,7 @@ from collections import defaultdict
|
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
|
-
from sqlalchemy import func, select
|
|
5
|
+
from sqlalchemy import and_, func, select
|
|
6
6
|
from strawberry.dataloader import AbstractCache, DataLoader
|
|
7
7
|
from typing_extensions import TypeAlias
|
|
8
8
|
|
|
@@ -37,43 +37,97 @@ class ExperimentAnnotationSummaryDataLoader(DataLoader[Key, Result]):
|
|
|
37
37
|
async def _load_fn(self, keys: list[Key]) -> list[Result]:
|
|
38
38
|
experiment_ids = keys
|
|
39
39
|
summaries: defaultdict[ExperimentID, Result] = defaultdict(list)
|
|
40
|
+
repetition_mean_scores_by_example_subquery = (
|
|
41
|
+
select(
|
|
42
|
+
models.ExperimentRun.experiment_id.label("experiment_id"),
|
|
43
|
+
models.ExperimentRunAnnotation.name.label("annotation_name"),
|
|
44
|
+
func.avg(models.ExperimentRunAnnotation.score).label("mean_repetition_score"),
|
|
45
|
+
)
|
|
46
|
+
.select_from(models.ExperimentRunAnnotation)
|
|
47
|
+
.join(
|
|
48
|
+
models.ExperimentRun,
|
|
49
|
+
models.ExperimentRunAnnotation.experiment_run_id == models.ExperimentRun.id,
|
|
50
|
+
)
|
|
51
|
+
.where(models.ExperimentRun.experiment_id.in_(experiment_ids))
|
|
52
|
+
.group_by(
|
|
53
|
+
models.ExperimentRun.experiment_id,
|
|
54
|
+
models.ExperimentRun.dataset_example_id,
|
|
55
|
+
models.ExperimentRunAnnotation.name,
|
|
56
|
+
)
|
|
57
|
+
.subquery()
|
|
58
|
+
.alias("repetition_mean_scores_by_example")
|
|
59
|
+
)
|
|
60
|
+
repetition_mean_scores_subquery = (
|
|
61
|
+
select(
|
|
62
|
+
repetition_mean_scores_by_example_subquery.c.experiment_id.label("experiment_id"),
|
|
63
|
+
repetition_mean_scores_by_example_subquery.c.annotation_name.label(
|
|
64
|
+
"annotation_name"
|
|
65
|
+
),
|
|
66
|
+
func.avg(repetition_mean_scores_by_example_subquery.c.mean_repetition_score).label(
|
|
67
|
+
"mean_score"
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
.select_from(repetition_mean_scores_by_example_subquery)
|
|
71
|
+
.group_by(
|
|
72
|
+
repetition_mean_scores_by_example_subquery.c.experiment_id,
|
|
73
|
+
repetition_mean_scores_by_example_subquery.c.annotation_name,
|
|
74
|
+
)
|
|
75
|
+
.subquery()
|
|
76
|
+
.alias("repetition_mean_scores")
|
|
77
|
+
)
|
|
78
|
+
repetitions_subquery = (
|
|
79
|
+
select(
|
|
80
|
+
models.ExperimentRun.experiment_id.label("experiment_id"),
|
|
81
|
+
models.ExperimentRunAnnotation.name.label("annotation_name"),
|
|
82
|
+
func.min(models.ExperimentRunAnnotation.score).label("min_score"),
|
|
83
|
+
func.max(models.ExperimentRunAnnotation.score).label("max_score"),
|
|
84
|
+
func.count().label("count"),
|
|
85
|
+
func.count(models.ExperimentRunAnnotation.error).label("error_count"),
|
|
86
|
+
)
|
|
87
|
+
.select_from(models.ExperimentRunAnnotation)
|
|
88
|
+
.join(
|
|
89
|
+
models.ExperimentRun,
|
|
90
|
+
models.ExperimentRunAnnotation.experiment_run_id == models.ExperimentRun.id,
|
|
91
|
+
)
|
|
92
|
+
.where(models.ExperimentRun.experiment_id.in_(experiment_ids))
|
|
93
|
+
.group_by(models.ExperimentRun.experiment_id, models.ExperimentRunAnnotation.name)
|
|
94
|
+
.subquery()
|
|
95
|
+
)
|
|
96
|
+
run_scores_query = (
|
|
97
|
+
select(
|
|
98
|
+
repetition_mean_scores_subquery.c.experiment_id.label("experiment_id"),
|
|
99
|
+
repetition_mean_scores_subquery.c.annotation_name.label("annotation_name"),
|
|
100
|
+
repetition_mean_scores_subquery.c.mean_score.label("mean_score"),
|
|
101
|
+
repetitions_subquery.c.min_score.label("min_score"),
|
|
102
|
+
repetitions_subquery.c.max_score.label("max_score"),
|
|
103
|
+
repetitions_subquery.c.count.label("count_"),
|
|
104
|
+
repetitions_subquery.c.error_count.label("error_count"),
|
|
105
|
+
)
|
|
106
|
+
.select_from(repetition_mean_scores_subquery)
|
|
107
|
+
.join(
|
|
108
|
+
repetitions_subquery,
|
|
109
|
+
and_(
|
|
110
|
+
repetitions_subquery.c.experiment_id
|
|
111
|
+
== repetition_mean_scores_subquery.c.experiment_id,
|
|
112
|
+
repetitions_subquery.c.annotation_name
|
|
113
|
+
== repetition_mean_scores_subquery.c.annotation_name,
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
.order_by(repetition_mean_scores_subquery.c.annotation_name)
|
|
117
|
+
)
|
|
40
118
|
async with self._db() as session:
|
|
41
|
-
async for (
|
|
42
|
-
experiment_id
|
|
43
|
-
annotation_name,
|
|
44
|
-
min_score,
|
|
45
|
-
max_score,
|
|
46
|
-
mean_score,
|
|
47
|
-
count,
|
|
48
|
-
error_count,
|
|
49
|
-
) in await session.stream(
|
|
50
|
-
select(
|
|
51
|
-
models.ExperimentRun.experiment_id,
|
|
52
|
-
models.ExperimentRunAnnotation.name,
|
|
53
|
-
func.min(models.ExperimentRunAnnotation.score),
|
|
54
|
-
func.max(models.ExperimentRunAnnotation.score),
|
|
55
|
-
func.avg(models.ExperimentRunAnnotation.score),
|
|
56
|
-
func.count(),
|
|
57
|
-
func.count(models.ExperimentRunAnnotation.error),
|
|
58
|
-
)
|
|
59
|
-
.join(
|
|
60
|
-
models.ExperimentRun,
|
|
61
|
-
models.ExperimentRunAnnotation.experiment_run_id == models.ExperimentRun.id,
|
|
62
|
-
)
|
|
63
|
-
.where(models.ExperimentRun.experiment_id.in_(experiment_ids))
|
|
64
|
-
.group_by(models.ExperimentRun.experiment_id, models.ExperimentRunAnnotation.name)
|
|
65
|
-
):
|
|
66
|
-
summaries[experiment_id].append(
|
|
119
|
+
async for scores_tuple in await session.stream(run_scores_query):
|
|
120
|
+
summaries[scores_tuple.experiment_id].append(
|
|
67
121
|
ExperimentAnnotationSummary(
|
|
68
|
-
annotation_name=annotation_name,
|
|
69
|
-
min_score=min_score,
|
|
70
|
-
max_score=max_score,
|
|
71
|
-
mean_score=mean_score,
|
|
72
|
-
count=
|
|
73
|
-
error_count=error_count,
|
|
122
|
+
annotation_name=scores_tuple.annotation_name,
|
|
123
|
+
min_score=scores_tuple.min_score,
|
|
124
|
+
max_score=scores_tuple.max_score,
|
|
125
|
+
mean_score=scores_tuple.mean_score,
|
|
126
|
+
count=scores_tuple.count_,
|
|
127
|
+
error_count=scores_tuple.error_count,
|
|
74
128
|
)
|
|
75
129
|
)
|
|
76
130
|
return [
|
|
77
131
|
sorted(summaries[experiment_id], key=lambda summary: summary.annotation_name)
|
|
78
|
-
for experiment_id in
|
|
132
|
+
for experiment_id in experiment_ids
|
|
79
133
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
|
-
from sqlalchemy import
|
|
3
|
+
from sqlalchemy import func, select
|
|
4
4
|
from strawberry.dataloader import DataLoader
|
|
5
5
|
from typing_extensions import TypeAlias
|
|
6
6
|
|
|
@@ -23,36 +23,29 @@ class ExperimentErrorRatesDataLoader(DataLoader[Key, Result]):
|
|
|
23
23
|
|
|
24
24
|
async def _load_fn(self, keys: list[Key]) -> list[Result]:
|
|
25
25
|
experiment_ids = keys
|
|
26
|
-
|
|
27
|
-
select(models.Experiment.id)
|
|
28
|
-
.where(models.Experiment.id.in_(set(experiment_ids)))
|
|
29
|
-
.subquery()
|
|
30
|
-
)
|
|
31
|
-
query = (
|
|
26
|
+
average_repetition_error_rates_subquery = (
|
|
32
27
|
select(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
(
|
|
36
|
-
|
|
37
|
-
func.count(models.ExperimentRun.error)
|
|
38
|
-
/ func.count(models.ExperimentRun.id),
|
|
39
|
-
),
|
|
40
|
-
else_=None,
|
|
41
|
-
),
|
|
28
|
+
models.ExperimentRun.experiment_id.label("experiment_id"),
|
|
29
|
+
(
|
|
30
|
+
func.count(models.ExperimentRun.error) / func.count(models.ExperimentRun.id)
|
|
31
|
+
).label("average_repetition_error_rate"),
|
|
42
32
|
)
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
.group_by(resolved_experiment_ids.c.id)
|
|
33
|
+
.where(models.ExperimentRun.experiment_id.in_(experiment_ids))
|
|
34
|
+
.group_by(models.ExperimentRun.dataset_example_id, models.ExperimentRun.experiment_id)
|
|
35
|
+
.subquery()
|
|
36
|
+
.alias("average_repetition_error_rates")
|
|
49
37
|
)
|
|
38
|
+
average_run_error_rates_query = select(
|
|
39
|
+
average_repetition_error_rates_subquery.c.experiment_id,
|
|
40
|
+
func.avg(average_repetition_error_rates_subquery.c.average_repetition_error_rate).label(
|
|
41
|
+
"average_run_error_rates"
|
|
42
|
+
),
|
|
43
|
+
).group_by(average_repetition_error_rates_subquery.c.experiment_id)
|
|
50
44
|
async with self._db() as session:
|
|
51
|
-
|
|
45
|
+
average_run_error_rates = {
|
|
52
46
|
experiment_id: error_rate
|
|
53
|
-
async for experiment_id, error_rate in await session.stream(
|
|
47
|
+
async for experiment_id, error_rate in await session.stream(
|
|
48
|
+
average_run_error_rates_query
|
|
49
|
+
)
|
|
54
50
|
}
|
|
55
|
-
return [
|
|
56
|
-
error_rates.get(experiment_id, ValueError(f"Unknown experiment ID: {experiment_id}"))
|
|
57
|
-
for experiment_id in keys
|
|
58
|
-
]
|
|
51
|
+
return [average_run_error_rates.get(experiment_id) for experiment_id in experiment_ids]
|
|
@@ -7,6 +7,7 @@ from phoenix.server.bearer_auth import is_authenticated
|
|
|
7
7
|
from .annotation_configs import router as annotation_configs_router
|
|
8
8
|
from .annotations import router as annotations_router
|
|
9
9
|
from .datasets import router as datasets_router
|
|
10
|
+
from .documents import router as documents_router
|
|
10
11
|
from .evaluations import router as evaluations_router
|
|
11
12
|
from .experiment_evaluations import router as experiment_evaluations_router
|
|
12
13
|
from .experiment_runs import router as experiment_runs_router
|
|
@@ -70,5 +71,6 @@ def create_v1_router(authentication_enabled: bool) -> APIRouter:
|
|
|
70
71
|
router.include_router(evaluations_router)
|
|
71
72
|
router.include_router(prompts_router)
|
|
72
73
|
router.include_router(projects_router)
|
|
74
|
+
router.include_router(documents_router)
|
|
73
75
|
router.include_router(users_router)
|
|
74
76
|
return router
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
from typing import Any, Literal, Optional
|
|
3
|
+
|
|
4
|
+
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
from sqlalchemy import select
|
|
7
|
+
from starlette.requests import Request
|
|
8
|
+
from starlette.status import HTTP_404_NOT_FOUND
|
|
9
|
+
from strawberry.relay import GlobalID
|
|
10
|
+
|
|
11
|
+
from phoenix.db import models
|
|
12
|
+
from phoenix.db.helpers import SupportedSQLDialect
|
|
13
|
+
from phoenix.db.insertion.helpers import as_kv, insert_on_conflict
|
|
14
|
+
from phoenix.db.insertion.types import Precursors
|
|
15
|
+
from phoenix.server.api.types.Evaluation import DocumentAnnotation
|
|
16
|
+
from phoenix.server.authorization import is_not_locked
|
|
17
|
+
from phoenix.server.bearer_auth import PhoenixUser
|
|
18
|
+
from phoenix.server.dml_event import DocumentAnnotationInsertEvent
|
|
19
|
+
|
|
20
|
+
from .models import V1RoutesBaseModel
|
|
21
|
+
from .spans import SpanAnnotationResult
|
|
22
|
+
from .utils import RequestBody, ResponseBody, add_errors_to_responses
|
|
23
|
+
|
|
24
|
+
# Since the document annotations are spans related, we place it under spans
|
|
25
|
+
router = APIRouter(tags=["spans"])
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SpanDocumentAnnotationData(V1RoutesBaseModel):
|
|
29
|
+
span_id: str = Field(description="OpenTelemetry Span ID (hex format w/o 0x prefix)")
|
|
30
|
+
name: str = Field(description="The name of the document annotation. E.x. relevance")
|
|
31
|
+
annotator_kind: Literal["LLM", "CODE", "HUMAN"] = Field(
|
|
32
|
+
description="The kind of annotator. E.g. llm judge, a heuristic piece of code, or a human"
|
|
33
|
+
)
|
|
34
|
+
document_position: int = Field(
|
|
35
|
+
description="A 0 based index of the document. E.x. the first document during retrieval is 0"
|
|
36
|
+
)
|
|
37
|
+
result: Optional[SpanAnnotationResult] = Field(
|
|
38
|
+
default=None, description="The score and or label of the annotation"
|
|
39
|
+
)
|
|
40
|
+
metadata: Optional[dict[str, Any]] = Field(
|
|
41
|
+
default=None, description="Metadata for custom values of the annotation"
|
|
42
|
+
)
|
|
43
|
+
identifier: str = Field(
|
|
44
|
+
default="",
|
|
45
|
+
description=(
|
|
46
|
+
"An custom ID for the annotation. "
|
|
47
|
+
"If provided, the annotation will be updated if it already exists."
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Precursor here means a value to add to a queue for processing async
|
|
52
|
+
def as_precursor(self, *, user_id: Optional[int] = None) -> Precursors.DocumentAnnotation:
|
|
53
|
+
return Precursors.DocumentAnnotation(
|
|
54
|
+
datetime.now(timezone.utc),
|
|
55
|
+
self.span_id,
|
|
56
|
+
self.document_position,
|
|
57
|
+
models.DocumentAnnotation(
|
|
58
|
+
name=self.name,
|
|
59
|
+
annotator_kind=self.annotator_kind,
|
|
60
|
+
document_position=self.document_position,
|
|
61
|
+
score=self.result.score if self.result else None,
|
|
62
|
+
label=self.result.label if self.result else None,
|
|
63
|
+
explanation=self.result.explanation if self.result else None,
|
|
64
|
+
metadata_=self.metadata or {},
|
|
65
|
+
identifier=self.identifier,
|
|
66
|
+
source="API",
|
|
67
|
+
user_id=user_id,
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class AnnotateSpanDocumentsRequestBody(RequestBody[list[SpanDocumentAnnotationData]]):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class InsertedSpanDocumentAnnotation(V1RoutesBaseModel):
|
|
77
|
+
id: str = Field(description="The ID of the inserted span document annotation")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class AnnotateSpanDocumentsResponseBody(ResponseBody[list[InsertedSpanDocumentAnnotation]]):
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@router.post(
|
|
85
|
+
"/document_annotations",
|
|
86
|
+
dependencies=[Depends(is_not_locked)],
|
|
87
|
+
operation_id="annotateSpanDocuments",
|
|
88
|
+
responses=add_errors_to_responses(
|
|
89
|
+
[
|
|
90
|
+
{
|
|
91
|
+
"status_code": HTTP_404_NOT_FOUND,
|
|
92
|
+
"description": "Span not found",
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
),
|
|
96
|
+
response_description="Span document annotation inserted successfully",
|
|
97
|
+
include_in_schema=True,
|
|
98
|
+
)
|
|
99
|
+
async def annotate_span_documents(
|
|
100
|
+
request: Request,
|
|
101
|
+
request_body: AnnotateSpanDocumentsRequestBody,
|
|
102
|
+
sync: bool = Query(
|
|
103
|
+
default=False, description="If set to true, the annotations are inserted synchronously."
|
|
104
|
+
),
|
|
105
|
+
) -> AnnotateSpanDocumentsResponseBody:
|
|
106
|
+
if not request_body.data:
|
|
107
|
+
return AnnotateSpanDocumentsResponseBody(data=[])
|
|
108
|
+
|
|
109
|
+
user_id: Optional[int] = None
|
|
110
|
+
if request.app.state.authentication_enabled and isinstance(request.user, PhoenixUser):
|
|
111
|
+
user_id = int(request.user.identity)
|
|
112
|
+
|
|
113
|
+
span_document_annotations = request_body.data
|
|
114
|
+
|
|
115
|
+
precursors = [
|
|
116
|
+
annotation.as_precursor(user_id=user_id) for annotation in span_document_annotations
|
|
117
|
+
]
|
|
118
|
+
if not sync:
|
|
119
|
+
await request.state.enqueue(*precursors)
|
|
120
|
+
|
|
121
|
+
span_ids = {p.span_id for p in precursors}
|
|
122
|
+
# Account for the fact that the spans could arrive after the annotation
|
|
123
|
+
async with request.app.state.db() as session:
|
|
124
|
+
existing_spans = {
|
|
125
|
+
span_id: (id_, num_docs)
|
|
126
|
+
async for span_id, id_, num_docs in await session.stream(
|
|
127
|
+
select(models.Span.span_id, models.Span.id, models.Span.num_documents).filter(
|
|
128
|
+
models.Span.span_id.in_(span_ids)
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
missing_span_ids = span_ids - set(existing_spans.keys())
|
|
134
|
+
# We prefer to fail the entire operation if there are missing spans in sync mode
|
|
135
|
+
if missing_span_ids:
|
|
136
|
+
raise HTTPException(
|
|
137
|
+
detail=f"Spans with IDs {', '.join(missing_span_ids)} do not exist.",
|
|
138
|
+
status_code=HTTP_404_NOT_FOUND,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Validate that document positions are within bounds
|
|
142
|
+
for annotation in span_document_annotations:
|
|
143
|
+
_, num_docs = existing_spans[annotation.span_id]
|
|
144
|
+
if annotation.document_position not in range(num_docs):
|
|
145
|
+
raise HTTPException(
|
|
146
|
+
detail=f"Document position {annotation.document_position} is out of bounds for "
|
|
147
|
+
f"span {annotation.span_id} (max: {num_docs - 1})",
|
|
148
|
+
status_code=422, # Unprocessable Entity
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
inserted_document_annotation_ids = []
|
|
152
|
+
dialect = SupportedSQLDialect(session.bind.dialect.name)
|
|
153
|
+
for anno in precursors:
|
|
154
|
+
span_rowid, _ = existing_spans[anno.span_id]
|
|
155
|
+
values = dict(as_kv(anno.as_insertable(span_rowid).row))
|
|
156
|
+
span_document_annotation_id = await session.scalar(
|
|
157
|
+
insert_on_conflict(
|
|
158
|
+
values,
|
|
159
|
+
dialect=dialect,
|
|
160
|
+
table=models.DocumentAnnotation,
|
|
161
|
+
unique_by=("name", "span_rowid", "identifier", "document_position"),
|
|
162
|
+
).returning(models.DocumentAnnotation.id)
|
|
163
|
+
)
|
|
164
|
+
inserted_document_annotation_ids.append(span_document_annotation_id)
|
|
165
|
+
|
|
166
|
+
# We queue an event to let the application know that annotations have changed
|
|
167
|
+
request.state.event_queue.put(
|
|
168
|
+
DocumentAnnotationInsertEvent(tuple(inserted_document_annotation_ids))
|
|
169
|
+
)
|
|
170
|
+
return AnnotateSpanDocumentsResponseBody(
|
|
171
|
+
data=[
|
|
172
|
+
InsertedSpanDocumentAnnotation(id=str(GlobalID(DocumentAnnotation.__name__, str(id_))))
|
|
173
|
+
for id_ in inserted_document_annotation_ids
|
|
174
|
+
]
|
|
175
|
+
)
|
|
@@ -949,9 +949,11 @@ async def annotate_spans(
|
|
|
949
949
|
span_ids = {p.span_id for p in precursors}
|
|
950
950
|
async with request.app.state.db() as session:
|
|
951
951
|
existing_spans = {
|
|
952
|
-
|
|
953
|
-
async for
|
|
954
|
-
select(models.Span
|
|
952
|
+
span_id: id_
|
|
953
|
+
async for span_id, id_ in await session.stream(
|
|
954
|
+
select(models.Span.span_id, models.Span.id).filter(
|
|
955
|
+
models.Span.span_id.in_(span_ids)
|
|
956
|
+
)
|
|
955
957
|
)
|
|
956
958
|
}
|
|
957
959
|
|
|
@@ -193,9 +193,11 @@ async def annotate_traces(
|
|
|
193
193
|
trace_ids = {p.trace_id for p in precursors}
|
|
194
194
|
async with request.app.state.db() as session:
|
|
195
195
|
existing_traces = {
|
|
196
|
-
|
|
197
|
-
async for
|
|
198
|
-
select(models.Trace
|
|
196
|
+
trace_id: id_
|
|
197
|
+
async for trace_id, id_ in await session.stream(
|
|
198
|
+
select(models.Trace.trace_id, models.Trace.id).filter(
|
|
199
|
+
models.Trace.trace_id.in_(trace_ids)
|
|
200
|
+
)
|
|
199
201
|
)
|
|
200
202
|
}
|
|
201
203
|
|