arize-phoenix 4.20.0__tar.gz → 4.20.1__tar.gz

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 (300) hide show
  1. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/PKG-INFO +2 -1
  2. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/pyproject.toml +2 -0
  3. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/bulk_inserter.py +24 -98
  4. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/document_annotation.py +13 -0
  5. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/span_annotation.py +13 -0
  6. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/trace_annotation.py +13 -0
  7. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/types.py +34 -28
  8. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/context.py +8 -6
  9. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/__init__.py +0 -47
  10. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/dataset_mutations.py +9 -3
  11. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/experiment_mutations.py +2 -0
  12. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/project_mutations.py +5 -5
  13. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/span_annotations_mutations.py +10 -2
  14. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +10 -2
  15. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/queries.py +9 -0
  16. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/datasets.py +2 -0
  17. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +2 -0
  18. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/experiment_runs.py +2 -0
  19. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/experiments.py +2 -0
  20. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/spans.py +12 -8
  21. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/traces.py +12 -10
  22. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Dataset.py +6 -1
  23. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Experiment.py +6 -1
  24. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Project.py +4 -1
  25. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Span.py +2 -2
  26. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/app.py +25 -8
  27. arize_phoenix-4.20.1/src/phoenix/server/dml_event.py +136 -0
  28. arize_phoenix-4.20.1/src/phoenix/server/dml_event_handler.py +272 -0
  29. arize_phoenix-4.20.1/src/phoenix/server/types.py +123 -0
  30. arize_phoenix-4.20.1/src/phoenix/version.py +1 -0
  31. arize_phoenix-4.20.0/src/phoenix/server/types.py +0 -18
  32. arize_phoenix-4.20.0/src/phoenix/version.py +0 -1
  33. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/.gitignore +0 -0
  34. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/IP_NOTICE +0 -0
  35. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/LICENSE +0 -0
  36. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/README.md +0 -0
  37. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/chat-service/chat/__init__.py +0 -0
  38. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/chat-service/chat/app.py +0 -0
  39. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/chat-service/chat/types.py +0 -0
  40. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/frontend/Dockerfile +0 -0
  41. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/frontend/Makefile +0 -0
  42. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/frontend/__init__.py +0 -0
  43. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/frontend/pyproject.toml +0 -0
  44. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/frontend/requirements.txt +0 -0
  45. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/examples/manually-instrumented-chatbot/frontend/schema.json +0 -0
  46. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/__init__.py +0 -0
  47. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/config.py +0 -0
  48. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/core/__init__.py +0 -0
  49. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/core/embedding_dimension.py +0 -0
  50. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/core/model.py +0 -0
  51. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/core/model_schema.py +0 -0
  52. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/core/model_schema_adapter.py +0 -0
  53. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/datetime_utils.py +0 -0
  54. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/README.md +0 -0
  55. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/__init__.py +0 -0
  56. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/alembic.ini +0 -0
  57. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/engines.py +0 -0
  58. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/helpers.py +0 -0
  59. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/__init__.py +0 -0
  60. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/constants.py +0 -0
  61. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/dataset.py +0 -0
  62. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/evaluation.py +0 -0
  63. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/helpers.py +0 -0
  64. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/insertion/span.py +0 -0
  65. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrate.py +0 -0
  66. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrations/__init__.py +0 -0
  67. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrations/env.py +0 -0
  68. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrations/script.py.mako +0 -0
  69. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrations/types.py +0 -0
  70. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  71. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  72. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/db/models.py +0 -0
  73. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/exceptions.py +0 -0
  74. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/__init__.py +0 -0
  75. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  76. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/evaluators/base.py +0 -0
  77. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  78. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  79. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/evaluators/utils.py +0 -0
  80. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/functions.py +0 -0
  81. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/tracing.py +0 -0
  82. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/types.py +0 -0
  83. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/experiments/utils.py +0 -0
  84. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/inferences/__init__.py +0 -0
  85. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/inferences/errors.py +0 -0
  86. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/inferences/fixtures.py +0 -0
  87. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/inferences/inferences.py +0 -0
  88. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/inferences/schema.py +0 -0
  89. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/inferences/validation.py +0 -0
  90. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/README.md +0 -0
  91. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/__init__.py +0 -0
  92. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/binning.py +0 -0
  93. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/metrics.py +0 -0
  94. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/mixins.py +0 -0
  95. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  96. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/timeseries.py +0 -0
  97. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/metrics/wrappers.py +0 -0
  98. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/pointcloud/__init__.py +0 -0
  99. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/pointcloud/clustering.py +0 -0
  100. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/pointcloud/pointcloud.py +0 -0
  101. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/pointcloud/projectors.py +0 -0
  102. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  103. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/py.typed +0 -0
  104. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/__init__.py +0 -0
  105. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/__init__.py +0 -0
  106. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  107. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  108. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  109. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  110. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  111. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  112. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  113. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  114. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  115. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/evaluation_summaries.py +0 -0
  116. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  117. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  118. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  119. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  120. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  121. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  122. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  123. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  124. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  125. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  126. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  127. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/span_evaluations.py +0 -0
  128. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  129. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  130. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/trace_evaluations.py +0 -0
  131. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/dataloaders/trace_row_ids.py +0 -0
  132. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/helpers/__init__.py +0 -0
  133. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  134. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  135. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  136. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  137. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  138. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  139. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  140. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  141. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  142. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  143. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  144. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  145. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  146. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  147. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  148. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  149. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  150. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  151. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  152. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  153. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  154. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  155. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  156. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  157. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  158. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  159. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  160. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  161. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/input_types/__init__.py +0 -0
  162. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/interceptor.py +0 -0
  163. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/__init__.py +0 -0
  164. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/auth.py +0 -0
  165. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  166. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/openapi/__init__.py +0 -0
  167. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/openapi/main.py +0 -0
  168. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/openapi/schema.py +0 -0
  169. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/__init__.py +0 -0
  170. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/utils.py +0 -0
  171. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/__init__.py +0 -0
  172. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  173. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/pydantic_compat.py +0 -0
  174. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  175. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/schema.py +0 -0
  176. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Annotation.py +0 -0
  177. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  178. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  179. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Cluster.py +0 -0
  180. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  181. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  182. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  183. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  184. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  185. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  186. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Dimension.py +0 -0
  187. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  188. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  189. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DimensionType.py +0 -0
  190. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  191. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  192. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  193. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  194. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  195. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Evaluation.py +0 -0
  196. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  197. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Event.py +0 -0
  198. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  199. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  200. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  201. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  202. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
  203. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  204. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  205. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Functionality.py +0 -0
  206. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Inferences.py +0 -0
  207. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  208. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  209. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/MimeType.py +0 -0
  210. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Model.py +0 -0
  211. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/NumericRange.py +0 -0
  212. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  213. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  214. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Retrieval.py +0 -0
  215. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  216. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Segments.py +0 -0
  217. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/SortDir.py +0 -0
  218. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  219. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  220. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/Trace.py +0 -0
  221. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  222. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  223. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  224. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  225. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/__init__.py +0 -0
  226. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/node.py +0 -0
  227. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/types/pagination.py +0 -0
  228. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/api/utils.py +0 -0
  229. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/grpc_server.py +0 -0
  230. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/main.py +0 -0
  231. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/openapi/__init__.py +0 -0
  232. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/prometheus.py +0 -0
  233. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/.vite/manifest.json +0 -0
  234. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  235. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  236. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  237. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  238. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  239. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  240. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  241. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  242. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/components-CAummAJx.js +0 -0
  243. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/index-Cg5hdf3g.js +0 -0
  244. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/pages-BU__X1UX.js +0 -0
  245. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/vendor-BMWfu6zp.js +0 -0
  246. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/vendor-DxkFTwjz.css +0 -0
  247. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/vendor-arizeai-CkyzG9Wl.js +0 -0
  248. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/vendor-codemirror-DO3VqEcD.js +0 -0
  249. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/vendor-recharts-BGN0SxgJ.js +0 -0
  250. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/assets/vendor-three-DwGkEfCM.js +0 -0
  251. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/favicon.ico +0 -0
  252. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/static/modernizr.js +0 -0
  253. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/telemetry.py +0 -0
  254. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/templates/__init__.py +0 -0
  255. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/templates/index.html +0 -0
  256. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/server/thread_server.py +0 -0
  257. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/services.py +0 -0
  258. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/session/__init__.py +0 -0
  259. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/session/client.py +0 -0
  260. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/session/data_extractor.py +0 -0
  261. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/session/evaluation.py +0 -0
  262. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/session/session.py +0 -0
  263. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/settings.py +0 -0
  264. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/__init__.py +0 -0
  265. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/attributes.py +0 -0
  266. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/dsl/README.md +0 -0
  267. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/dsl/__init__.py +0 -0
  268. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/dsl/filter.py +0 -0
  269. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/dsl/helpers.py +0 -0
  270. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/dsl/query.py +0 -0
  271. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/errors.py +0 -0
  272. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/evaluation_conventions.py +0 -0
  273. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/exporter.py +0 -0
  274. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/fixtures.py +0 -0
  275. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/langchain/__init__.py +0 -0
  276. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/langchain/instrumentor.py +0 -0
  277. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/llama_index/__init__.py +0 -0
  278. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/llama_index/callback.py +0 -0
  279. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/openai/__init__.py +0 -0
  280. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/openai/instrumentor.py +0 -0
  281. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/otel.py +0 -0
  282. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/projects.py +0 -0
  283. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/schemas.py +0 -0
  284. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/span_evaluations.py +0 -0
  285. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/span_json_decoder.py +0 -0
  286. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/span_json_encoder.py +0 -0
  287. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/trace_dataset.py +0 -0
  288. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/utils.py +0 -0
  289. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/v1/__init__.py +0 -0
  290. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  291. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  292. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/__init__.py +0 -0
  293. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/client.py +0 -0
  294. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/deprecation.py +0 -0
  295. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/error_handling.py +0 -0
  296. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/json.py +0 -0
  297. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/logging.py +0 -0
  298. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/project.py +0 -0
  299. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/re.py +0 -0
  300. {arize_phoenix-4.20.0 → arize_phoenix-4.20.1}/src/phoenix/utilities/span_store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arize-phoenix
3
- Version: 4.20.0
3
+ Version: 4.20.1
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
@@ -96,6 +96,7 @@ Requires-Dist: ruff==0.5.4; extra == 'dev'
96
96
  Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.236.0; extra == 'dev'
97
97
  Requires-Dist: tabulate; extra == 'dev'
98
98
  Requires-Dist: types-tabulate; extra == 'dev'
99
+ Requires-Dist: uvloop; (platform_system != 'Windows') and extra == 'dev'
99
100
  Provides-Extra: evals
100
101
  Provides-Extra: experimental
101
102
  Provides-Extra: llama-index
@@ -94,6 +94,7 @@ dev = [
94
94
  "prometheus_client",
95
95
  "asgi-lifespan",
96
96
  "Faker>=26.0.0",
97
+ "uvloop; platform_system != 'Windows'",
97
98
  ]
98
99
  evals = []
99
100
  experimental = []
@@ -173,6 +174,7 @@ dependencies = [
173
174
  "astunparse; python_version<'3.9'", # `ast.unparse(...)` is only available starting with Python 3.9
174
175
  "asgi-lifespan",
175
176
  "Faker>=26.0.0",
177
+ "uvloop; platform_system != 'Windows'",
176
178
  ]
177
179
 
178
180
  [tool.hatch.envs.type]
@@ -1,38 +1,29 @@
1
1
  import asyncio
2
2
  import logging
3
3
  from asyncio import Queue, as_completed
4
- from collections import defaultdict
5
4
  from dataclasses import dataclass, field
6
- from datetime import datetime, timezone
7
5
  from functools import singledispatchmethod
8
6
  from itertools import islice
9
7
  from time import perf_counter
10
8
  from typing import (
11
9
  Any,
10
+ AsyncIterator,
12
11
  Awaitable,
13
12
  Callable,
14
- DefaultDict,
15
- Dict,
16
13
  Iterable,
17
14
  List,
18
- Mapping,
19
15
  Optional,
20
16
  Set,
21
17
  Tuple,
22
- Type,
23
18
  cast,
24
19
  )
25
20
 
26
- from cachetools import LRUCache
27
- from sqlalchemy import Select, select
28
21
  from typing_extensions import TypeAlias
29
22
 
30
23
  import phoenix.trace.v1 as pb
31
- from phoenix.db import models
32
24
  from phoenix.db.insertion.constants import DEFAULT_RETRY_ALLOWANCE, DEFAULT_RETRY_DELAY_SEC
33
25
  from phoenix.db.insertion.document_annotation import DocumentAnnotationQueueInserter
34
26
  from phoenix.db.insertion.evaluation import (
35
- EvaluationInsertionEvent,
36
27
  InsertEvaluationError,
37
28
  insert_evaluation,
38
29
  )
@@ -41,8 +32,8 @@ from phoenix.db.insertion.span import SpanInsertionEvent, insert_span
41
32
  from phoenix.db.insertion.span_annotation import SpanAnnotationQueueInserter
42
33
  from phoenix.db.insertion.trace_annotation import TraceAnnotationQueueInserter
43
34
  from phoenix.db.insertion.types import Insertables, Precursors
44
- from phoenix.server.api.dataloaders import CacheForDataLoaders
45
- from phoenix.server.types import DbSessionFactory
35
+ from phoenix.server.dml_event import DmlEvent, SpanInsertEvent
36
+ from phoenix.server.types import CanPutItem, DbSessionFactory
46
37
  from phoenix.trace.schemas import Span
47
38
 
48
39
  logger = logging.getLogger(__name__)
@@ -60,8 +51,7 @@ class BulkInserter:
60
51
  self,
61
52
  db: DbSessionFactory,
62
53
  *,
63
- cache_for_dataloaders: Optional[CacheForDataLoaders] = None,
64
- initial_batch_of_operations: Iterable[DataManipulation] = (),
54
+ event_queue: CanPutItem[DmlEvent],
65
55
  initial_batch_of_spans: Optional[Iterable[Tuple[Span, str]]] = None,
66
56
  initial_batch_of_evaluations: Optional[Iterable[pb.Evaluation]] = None,
67
57
  sleep: float = 0.1,
@@ -93,18 +83,12 @@ class BulkInserter:
93
83
  [] if initial_batch_of_evaluations is None else list(initial_batch_of_evaluations)
94
84
  )
95
85
  self._task: Optional[asyncio.Task[None]] = None
96
- self._last_updated_at_by_project: LRUCache[ProjectRowId, datetime] = LRUCache(maxsize=100)
97
- self._cache_for_dataloaders = cache_for_dataloaders
86
+ self._event_queue = event_queue
98
87
  self._enable_prometheus = enable_prometheus
99
88
  self._retry_delay_sec = retry_delay_sec
100
89
  self._retry_allowance = retry_allowance
101
90
  self._queue_inserters = _QueueInserters(db, self._retry_delay_sec, self._retry_allowance)
102
91
 
103
- def last_updated_at(self, project_rowid: Optional[ProjectRowId] = None) -> Optional[datetime]:
104
- if isinstance(project_rowid, ProjectRowId):
105
- return self._last_updated_at_by_project.get(project_rowid)
106
- return max(self._last_updated_at_by_project.values(), default=None)
107
-
108
92
  async def __aenter__(
109
93
  self,
110
94
  ) -> Tuple[
@@ -162,21 +146,20 @@ class BulkInserter:
162
146
  ):
163
147
  await asyncio.sleep(self._sleep)
164
148
  continue
165
- ops_remaining, events = self._max_ops_per_transaction, []
149
+ ops_remaining = self._max_ops_per_transaction
166
150
  async with self._db() as session:
167
151
  while ops_remaining and not self._operations.empty():
168
152
  ops_remaining -= 1
169
153
  op = await self._operations.get()
170
154
  try:
171
155
  async with session.begin_nested():
172
- events.append(await op(session))
156
+ await op(session)
173
157
  except Exception as e:
174
158
  if self._enable_prometheus:
175
159
  from phoenix.server.prometheus import BULK_LOADER_EXCEPTIONS
176
160
 
177
161
  BULK_LOADER_EXCEPTIONS.inc()
178
162
  logger.exception(str(e))
179
- await self._process_events(events)
180
163
  # It's important to grab the buffers at the same time so there's
181
164
  # no race condition, since an eval insertion will fail if the span
182
165
  # it references doesn't exist. Grabbing the eval buffer later may
@@ -190,25 +173,18 @@ class BulkInserter:
190
173
  self._evaluations = []
191
174
  # Spans should be inserted before the evaluations, since an evaluation
192
175
  # insertion will fail if the span it references doesn't exist.
193
- transaction_result = TransactionResult()
194
176
  if spans_buffer:
195
- result = await self._insert_spans(spans_buffer)
196
- transaction_result.updated_project_rowids.update(result.updated_project_rowids)
177
+ await self._insert_spans(spans_buffer)
197
178
  spans_buffer = None
198
179
  if evaluations_buffer:
199
- result = await self._insert_evaluations(evaluations_buffer)
200
- transaction_result.updated_project_rowids.update(result.updated_project_rowids)
180
+ await self._insert_evaluations(evaluations_buffer)
201
181
  evaluations_buffer = None
202
- for project_rowid in transaction_result.updated_project_rowids:
203
- self._last_updated_at_by_project[project_rowid] = datetime.now(timezone.utc)
204
- if not self._queue_inserters.empty:
205
- if inserted_ids := await self._queue_inserters.insert():
206
- for project_rowid in await self._get_project_rowids(inserted_ids):
207
- self._last_updated_at_by_project[project_rowid] = datetime.now(timezone.utc)
182
+ async for event in self._queue_inserters.insert():
183
+ self._event_queue.put(event)
208
184
  await asyncio.sleep(self._sleep)
209
185
 
210
- async def _insert_spans(self, spans: List[Tuple[Span, str]]) -> TransactionResult:
211
- transaction_result = TransactionResult()
186
+ async def _insert_spans(self, spans: List[Tuple[Span, str]]) -> None:
187
+ project_ids = set()
212
188
  for i in range(0, len(spans), self._max_ops_per_transaction):
213
189
  try:
214
190
  start = perf_counter()
@@ -231,9 +207,7 @@ class BulkInserter:
231
207
  f"Failed to insert span with span_id={span.context.span_id}"
232
208
  )
233
209
  if result is not None:
234
- transaction_result.updated_project_rowids.add(result.project_rowid)
235
- if (cache := self._cache_for_dataloaders) is not None:
236
- cache.invalidate(result)
210
+ project_ids.add(result.project_rowid)
237
211
  if self._enable_prometheus:
238
212
  from phoenix.server.prometheus import BULK_LOADER_INSERTION_TIME
239
213
 
@@ -244,10 +218,9 @@ class BulkInserter:
244
218
 
245
219
  BULK_LOADER_EXCEPTIONS.inc()
246
220
  logger.exception("Failed to insert spans")
247
- return transaction_result
221
+ self._event_queue.put(SpanInsertEvent(tuple(project_ids)))
248
222
 
249
- async def _insert_evaluations(self, evaluations: List[pb.Evaluation]) -> TransactionResult:
250
- transaction_result = TransactionResult()
223
+ async def _insert_evaluations(self, evaluations: List[pb.Evaluation]) -> None:
251
224
  for i in range(0, len(evaluations), self._max_ops_per_transaction):
252
225
  try:
253
226
  start = perf_counter()
@@ -257,20 +230,15 @@ class BulkInserter:
257
230
  from phoenix.server.prometheus import BULK_LOADER_EVALUATION_INSERTIONS
258
231
 
259
232
  BULK_LOADER_EVALUATION_INSERTIONS.inc()
260
- result: Optional[EvaluationInsertionEvent] = None
261
233
  try:
262
234
  async with session.begin_nested():
263
- result = await insert_evaluation(session, evaluation)
235
+ await insert_evaluation(session, evaluation)
264
236
  except InsertEvaluationError as error:
265
237
  if self._enable_prometheus:
266
238
  from phoenix.server.prometheus import BULK_LOADER_EXCEPTIONS
267
239
 
268
240
  BULK_LOADER_EXCEPTIONS.inc()
269
241
  logger.exception(f"Failed to insert evaluation: {str(error)}")
270
- if result is not None:
271
- transaction_result.updated_project_rowids.add(result.project_rowid)
272
- if (cache := self._cache_for_dataloaders) is not None:
273
- cache.invalidate(result)
274
242
  if self._enable_prometheus:
275
243
  from phoenix.server.prometheus import BULK_LOADER_INSERTION_TIME
276
244
 
@@ -281,48 +249,6 @@ class BulkInserter:
281
249
 
282
250
  BULK_LOADER_EXCEPTIONS.inc()
283
251
  logger.exception("Failed to insert evaluations")
284
- return transaction_result
285
-
286
- async def _get_project_rowids(
287
- self,
288
- inserted_ids: Mapping[Type[models.Base], List[int]],
289
- ) -> Set[int]:
290
- ans: Set[int] = set()
291
- if not inserted_ids:
292
- return ans
293
- stmt: Select[Tuple[int]]
294
- for table, ids in inserted_ids.items():
295
- if not ids:
296
- continue
297
- if issubclass(table, models.SpanAnnotation):
298
- stmt = (
299
- select(models.Project.id)
300
- .join(models.Trace)
301
- .join_from(models.Trace, models.Span)
302
- .join_from(models.Span, models.SpanAnnotation)
303
- .where(models.SpanAnnotation.id.in_(ids))
304
- )
305
- elif issubclass(table, models.DocumentAnnotation):
306
- stmt = (
307
- select(models.Project.id)
308
- .join(models.Trace)
309
- .join_from(models.Trace, models.Span)
310
- .join_from(models.Span, models.DocumentAnnotation)
311
- .where(models.DocumentAnnotation.id.in_(ids))
312
- )
313
- elif issubclass(table, models.TraceAnnotation):
314
- stmt = (
315
- select(models.Project.id)
316
- .join(models.Trace)
317
- .join_from(models.Trace, models.TraceAnnotation)
318
- .where(models.TraceAnnotation.id.in_(ids))
319
- )
320
- else:
321
- continue
322
- async with self._db() as session:
323
- project_rowids = [_ async for _ in await session.stream_scalars(stmt)]
324
- ans.update(project_rowids)
325
- return ans
326
252
 
327
253
 
328
254
  class _QueueInserters:
@@ -343,13 +269,13 @@ class _QueueInserters:
343
269
  self._document_annotations,
344
270
  )
345
271
 
346
- async def insert(self) -> Dict[Type[models.Base], List[int]]:
347
- ans: DefaultDict[Type[models.Base], List[int]] = defaultdict(list)
348
- for coro in as_completed([q.insert() for q in self._queues]):
349
- table, inserted_ids = await coro
350
- if inserted_ids:
351
- ans[table].extend(inserted_ids)
352
- return ans
272
+ async def insert(self) -> AsyncIterator[DmlEvent]:
273
+ if self.empty:
274
+ return
275
+ for coro in as_completed([q.insert() for q in self._queues if not q.empty]):
276
+ if events := cast(Optional[List[DmlEvent]], await coro):
277
+ for event in events:
278
+ yield event
353
279
 
354
280
  @property
355
281
  def empty(self) -> bool:
@@ -7,6 +7,7 @@ from typing_extensions import TypeAlias
7
7
 
8
8
  from phoenix.db import models
9
9
  from phoenix.db.helpers import dedup, num_docs_col
10
+ from phoenix.db.insertion.helpers import as_kv
10
11
  from phoenix.db.insertion.types import (
11
12
  Insertables,
12
13
  Postponed,
@@ -14,6 +15,7 @@ from phoenix.db.insertion.types import (
14
15
  QueueInserter,
15
16
  Received,
16
17
  )
18
+ from phoenix.server.dml_event import DocumentAnnotationDmlEvent
17
19
 
18
20
  _Name: TypeAlias = str
19
21
  _SpanId: TypeAlias = str
@@ -40,10 +42,21 @@ class DocumentAnnotationQueueInserter(
40
42
  Precursors.DocumentAnnotation,
41
43
  Insertables.DocumentAnnotation,
42
44
  models.DocumentAnnotation,
45
+ DocumentAnnotationDmlEvent,
43
46
  ],
44
47
  table=models.DocumentAnnotation,
45
48
  unique_by=("name", "span_rowid", "document_position"),
46
49
  ):
50
+ async def _events(
51
+ self,
52
+ session: AsyncSession,
53
+ *insertions: Insertables.DocumentAnnotation,
54
+ ) -> List[DocumentAnnotationDmlEvent]:
55
+ records = [dict(as_kv(ins.row)) for ins in insertions]
56
+ stmt = self._insert_on_conflict(*records).returning(self.table.id)
57
+ ids = tuple([_ async for _ in await session.stream_scalars(stmt)])
58
+ return [DocumentAnnotationDmlEvent(ids)]
59
+
47
60
  async def _partition(
48
61
  self,
49
62
  session: AsyncSession,
@@ -7,6 +7,7 @@ from typing_extensions import TypeAlias
7
7
 
8
8
  from phoenix.db import models
9
9
  from phoenix.db.helpers import dedup
10
+ from phoenix.db.insertion.helpers import as_kv
10
11
  from phoenix.db.insertion.types import (
11
12
  Insertables,
12
13
  Postponed,
@@ -14,6 +15,7 @@ from phoenix.db.insertion.types import (
14
15
  QueueInserter,
15
16
  Received,
16
17
  )
18
+ from phoenix.server.dml_event import SpanAnnotationDmlEvent
17
19
 
18
20
  _Name: TypeAlias = str
19
21
  _SpanId: TypeAlias = str
@@ -36,10 +38,21 @@ class SpanAnnotationQueueInserter(
36
38
  Precursors.SpanAnnotation,
37
39
  Insertables.SpanAnnotation,
38
40
  models.SpanAnnotation,
41
+ SpanAnnotationDmlEvent,
39
42
  ],
40
43
  table=models.SpanAnnotation,
41
44
  unique_by=("name", "span_rowid"),
42
45
  ):
46
+ async def _events(
47
+ self,
48
+ session: AsyncSession,
49
+ *insertions: Insertables.SpanAnnotation,
50
+ ) -> List[SpanAnnotationDmlEvent]:
51
+ records = [dict(as_kv(ins.row)) for ins in insertions]
52
+ stmt = self._insert_on_conflict(*records).returning(self.table.id)
53
+ ids = tuple([_ async for _ in await session.stream_scalars(stmt)])
54
+ return [SpanAnnotationDmlEvent(ids)]
55
+
43
56
  async def _partition(
44
57
  self,
45
58
  session: AsyncSession,
@@ -7,6 +7,7 @@ from typing_extensions import TypeAlias
7
7
 
8
8
  from phoenix.db import models
9
9
  from phoenix.db.helpers import dedup
10
+ from phoenix.db.insertion.helpers import as_kv
10
11
  from phoenix.db.insertion.types import (
11
12
  Insertables,
12
13
  Postponed,
@@ -14,6 +15,7 @@ from phoenix.db.insertion.types import (
14
15
  QueueInserter,
15
16
  Received,
16
17
  )
18
+ from phoenix.server.dml_event import TraceAnnotationDmlEvent
17
19
 
18
20
  _Name: TypeAlias = str
19
21
  _TraceId: TypeAlias = str
@@ -36,10 +38,21 @@ class TraceAnnotationQueueInserter(
36
38
  Precursors.TraceAnnotation,
37
39
  Insertables.TraceAnnotation,
38
40
  models.TraceAnnotation,
41
+ TraceAnnotationDmlEvent,
39
42
  ],
40
43
  table=models.TraceAnnotation,
41
44
  unique_by=("name", "trace_rowid"),
42
45
  ):
46
+ async def _events(
47
+ self,
48
+ session: AsyncSession,
49
+ *insertions: Insertables.TraceAnnotation,
50
+ ) -> List[TraceAnnotationDmlEvent]:
51
+ records = [dict(as_kv(ins.row)) for ins in insertions]
52
+ stmt = self._insert_on_conflict(*records).returning(self.table.id)
53
+ ids = tuple([_ async for _ in await session.stream_scalars(stmt)])
54
+ return [TraceAnnotationDmlEvent(ids)]
55
+
43
56
  async def _partition(
44
57
  self,
45
58
  session: AsyncSession,
@@ -21,11 +21,12 @@ from typing import (
21
21
  )
22
22
 
23
23
  from sqlalchemy.ext.asyncio import AsyncSession
24
- from sqlalchemy.sql.dml import ReturningInsert
24
+ from sqlalchemy.sql.dml import Insert
25
25
 
26
26
  from phoenix.db import models
27
27
  from phoenix.db.insertion.constants import DEFAULT_RETRY_ALLOWANCE, DEFAULT_RETRY_DELAY_SEC
28
- from phoenix.db.insertion.helpers import as_kv, insert_on_conflict
28
+ from phoenix.db.insertion.helpers import insert_on_conflict
29
+ from phoenix.server.dml_event import DmlEvent
29
30
  from phoenix.server.types import DbSessionFactory
30
31
 
31
32
  logger = logging.getLogger("__name__")
@@ -40,6 +41,7 @@ _AnyT = TypeVar("_AnyT")
40
41
  _PrecursorT = TypeVar("_PrecursorT")
41
42
  _InsertableT = TypeVar("_InsertableT", bound=Insertable)
42
43
  _RowT = TypeVar("_RowT", bound=models.Base)
44
+ _DmlEventT = TypeVar("_DmlEventT", bound=DmlEvent)
43
45
 
44
46
 
45
47
  @dataclass(frozen=True)
@@ -56,7 +58,7 @@ class Postponed(Received[_AnyT]):
56
58
  retries_left: int = field(default=DEFAULT_RETRY_ALLOWANCE)
57
59
 
58
60
 
59
- class QueueInserter(ABC, Generic[_PrecursorT, _InsertableT, _RowT]):
61
+ class QueueInserter(ABC, Generic[_PrecursorT, _InsertableT, _RowT, _DmlEventT]):
60
62
  table: Type[_RowT]
61
63
  unique_by: Sequence[str]
62
64
 
@@ -97,59 +99,63 @@ class QueueInserter(ABC, Generic[_PrecursorT, _InsertableT, _RowT]):
97
99
  List[Received[_PrecursorT]],
98
100
  ]: ...
99
101
 
100
- async def insert(self) -> Tuple[Type[_RowT], List[int]]:
102
+ async def insert(self) -> Optional[List[_DmlEventT]]:
101
103
  if not self._queue:
102
- return self.table, []
103
- parcels = self._queue
104
- self._queue = []
105
- inserted_ids: List[int] = []
104
+ return None
105
+ self._queue, parcels = [], self._queue
106
+ events: List[_DmlEventT] = []
106
107
  async with self._db() as session:
107
108
  to_insert, to_postpone, _ = await self._partition(session, *parcels)
108
109
  if to_insert:
109
- inserted_ids, to_retry, _ = await self._insert(session, *to_insert)
110
- to_postpone.extend(to_retry)
110
+ events, to_retry, _ = await self._insert(session, *to_insert)
111
+ if to_retry:
112
+ to_postpone.extend(to_retry)
111
113
  if to_postpone:
112
114
  loop = asyncio.get_running_loop()
113
115
  loop.call_later(self._retry_delay_sec, self._queue.extend, to_postpone)
114
- return self.table, inserted_ids
116
+ return events
115
117
 
116
- def _stmt(self, *records: Mapping[str, Any]) -> ReturningInsert[Tuple[int]]:
117
- pk = next(c for c in self.table.__table__.c if c.primary_key)
118
+ def _insert_on_conflict(self, *records: Mapping[str, Any]) -> Insert:
118
119
  return insert_on_conflict(
119
120
  *records,
120
121
  table=self.table,
121
122
  unique_by=self.unique_by,
122
123
  dialect=self._db.dialect,
123
- ).returning(pk)
124
+ )
125
+
126
+ @abstractmethod
127
+ async def _events(
128
+ self,
129
+ session: AsyncSession,
130
+ *insertions: _InsertableT,
131
+ ) -> List[_DmlEventT]: ...
124
132
 
125
133
  async def _insert(
126
134
  self,
127
135
  session: AsyncSession,
128
- *insertions: Received[_InsertableT],
129
- ) -> Tuple[List[int], List[Postponed[_PrecursorT]], List[Received[_InsertableT]]]:
130
- records = [dict(as_kv(ins.item.row)) for ins in insertions]
131
- inserted_ids: List[int] = []
136
+ *parcels: Received[_InsertableT],
137
+ ) -> Tuple[
138
+ List[_DmlEventT],
139
+ List[Postponed[_PrecursorT]],
140
+ List[Received[_InsertableT]],
141
+ ]:
132
142
  to_retry: List[Postponed[_PrecursorT]] = []
133
143
  failures: List[Received[_InsertableT]] = []
134
- stmt = self._stmt(*records)
144
+ events: List[_DmlEventT] = []
135
145
  try:
136
146
  async with session.begin_nested():
137
- ids = [id_ async for id_ in await session.stream_scalars(stmt)]
138
- inserted_ids.extend(ids)
147
+ events.extend(await self._events(session, *(p.item for p in parcels)))
139
148
  except BaseException:
140
149
  logger.exception(
141
150
  f"Failed to bulk insert for {self.table.__name__}. "
142
- f"Will try to insert ({len(records)} records) individually instead."
151
+ f"Will try to insert ({len(parcels)} records) individually instead."
143
152
  )
144
- for i, record in enumerate(records):
145
- stmt = self._stmt(record)
153
+ for p in parcels:
146
154
  try:
147
155
  async with session.begin_nested():
148
- ids = [id_ async for id_ in await session.stream_scalars(stmt)]
149
- inserted_ids.extend(ids)
156
+ events.extend(await self._events(session, p.item))
150
157
  except BaseException:
151
158
  logger.exception(f"Failed to insert for {self.table.__name__}.")
152
- p = insertions[i]
153
159
  if isinstance(p, Postponed) and p.retries_left == 1:
154
160
  failures.append(p)
155
161
  else:
@@ -162,7 +168,7 @@ class QueueInserter(ABC, Generic[_PrecursorT, _InsertableT, _RowT]):
162
168
  else self._retry_allowance,
163
169
  )
164
170
  )
165
- return inserted_ids, to_retry, failures
171
+ return events, to_retry, failures
166
172
 
167
173
 
168
174
  class Precursors(ABC):
@@ -1,10 +1,8 @@
1
1
  from dataclasses import dataclass
2
- from datetime import datetime
3
2
  from pathlib import Path
4
- from typing import Callable, Optional
3
+ from typing import Any, Optional
5
4
 
6
5
  from strawberry.fastapi import BaseContext
7
- from typing_extensions import TypeAlias
8
6
 
9
7
  from phoenix.core.model_schema import Model
10
8
  from phoenix.server.api.dataloaders import (
@@ -34,7 +32,8 @@ from phoenix.server.api.dataloaders import (
34
32
  TraceEvaluationsDataLoader,
35
33
  TraceRowIdsDataLoader,
36
34
  )
37
- from phoenix.server.types import DbSessionFactory
35
+ from phoenix.server.dml_event import DmlEvent
36
+ from phoenix.server.types import CanGetLastUpdatedAt, CanPutItem, DbSessionFactory
38
37
 
39
38
 
40
39
  @dataclass
@@ -65,7 +64,9 @@ class DataLoaders:
65
64
  project_by_name: ProjectByNameDataLoader
66
65
 
67
66
 
68
- ProjectRowId: TypeAlias = int
67
+ class _NoOp:
68
+ def get(self, *args: Any, **kwargs: Any) -> Any: ...
69
+ def put(self, *args: Any, **kwargs: Any) -> Any: ...
69
70
 
70
71
 
71
72
  @dataclass
@@ -75,6 +76,7 @@ class Context(BaseContext):
75
76
  cache_for_dataloaders: Optional[CacheForDataLoaders]
76
77
  model: Model
77
78
  export_path: Path
79
+ last_updated_at: CanGetLastUpdatedAt = _NoOp()
80
+ event_queue: CanPutItem[DmlEvent] = _NoOp()
78
81
  corpus: Optional[Model] = None
79
- streaming_last_updated_at: Callable[[ProjectRowId], Optional[datetime]] = lambda _: None
80
82
  read_only: bool = False
@@ -1,12 +1,4 @@
1
1
  from dataclasses import dataclass, field
2
- from functools import singledispatchmethod
3
-
4
- from phoenix.db.insertion.evaluation import (
5
- DocumentEvaluationInsertionEvent,
6
- SpanEvaluationInsertionEvent,
7
- TraceEvaluationInsertionEvent,
8
- )
9
- from phoenix.db.insertion.span import ClearProjectSpansEvent, SpanInsertionEvent
10
2
 
11
3
  from .annotation_summaries import AnnotationSummaryCache, AnnotationSummaryDataLoader
12
4
  from .average_experiment_run_latency import AverageExperimentRunLatencyDataLoader
@@ -88,42 +80,3 @@ class CacheForDataLoaders:
88
80
  token_count: TokenCountCache = field(
89
81
  default_factory=TokenCountCache,
90
82
  )
91
-
92
- def _update_spans(self, project_rowid: int) -> None:
93
- self.latency_ms_quantile.invalidate(project_rowid)
94
- self.token_count.invalidate(project_rowid)
95
- self.record_count.invalidate(project_rowid)
96
- self.min_start_or_max_end_time.invalidate(project_rowid)
97
-
98
- def _clear_spans(self, project_rowid: int) -> None:
99
- self._update_spans(project_rowid)
100
- self.annotation_summary.invalidate_project(project_rowid)
101
- self.evaluation_summary.invalidate_project(project_rowid)
102
- self.document_evaluation_summary.invalidate_project(project_rowid)
103
-
104
- @singledispatchmethod
105
- def invalidate(self, event: SpanInsertionEvent) -> None:
106
- project_rowid, *_ = event
107
- self._update_spans(project_rowid)
108
-
109
- @invalidate.register
110
- def _(self, event: ClearProjectSpansEvent) -> None:
111
- project_rowid, *_ = event
112
- self._clear_spans(project_rowid)
113
-
114
- @invalidate.register
115
- def _(self, event: DocumentEvaluationInsertionEvent) -> None:
116
- project_rowid, evaluation_name = event
117
- self.document_evaluation_summary.invalidate((project_rowid, evaluation_name))
118
-
119
- @invalidate.register
120
- def _(self, event: SpanEvaluationInsertionEvent) -> None:
121
- project_rowid, evaluation_name = event
122
- self.annotation_summary.invalidate((project_rowid, evaluation_name, "span"))
123
- self.evaluation_summary.invalidate((project_rowid, evaluation_name, "span"))
124
-
125
- @invalidate.register
126
- def _(self, event: TraceEvaluationInsertionEvent) -> None:
127
- project_rowid, evaluation_name = event
128
- self.annotation_summary.invalidate((project_rowid, evaluation_name, "trace"))
129
- self.evaluation_summary.invalidate((project_rowid, evaluation_name, "trace"))