arize-phoenix 3.18.1__tar.gz → 3.19.0__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 (184) hide show
  1. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/PKG-INFO +2 -1
  2. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/pyproject.toml +1 -0
  3. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/project.py +152 -11
  4. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Evaluation.py +21 -1
  5. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Project.py +53 -3
  6. arize_phoenix-3.19.0/src/phoenix/server/api/types/Trace.py +47 -0
  7. arize_phoenix-3.19.0/src/phoenix/server/static/index.js +7472 -0
  8. arize_phoenix-3.19.0/src/phoenix/trace/__init__.py +15 -0
  9. arize_phoenix-3.19.0/src/phoenix/version.py +1 -0
  10. arize_phoenix-3.18.1/src/phoenix/server/static/index.js +0 -7452
  11. arize_phoenix-3.18.1/src/phoenix/trace/__init__.py +0 -35
  12. arize_phoenix-3.18.1/src/phoenix/version.py +0 -1
  13. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/.gitignore +0 -0
  14. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/IP_NOTICE +0 -0
  15. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/LICENSE +0 -0
  16. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/README.md +0 -0
  17. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/__init__.py +0 -0
  18. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/config.py +0 -0
  19. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/__init__.py +0 -0
  20. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/embedding_dimension.py +0 -0
  21. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/model.py +0 -0
  22. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/model_schema.py +0 -0
  23. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  24. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/core/traces.py +0 -0
  25. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datasets/__init__.py +0 -0
  26. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datasets/dataset.py +0 -0
  27. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datasets/errors.py +0 -0
  28. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datasets/fixtures.py +0 -0
  29. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datasets/schema.py +0 -0
  30. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datasets/validation.py +0 -0
  31. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/datetime_utils.py +0 -0
  32. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/exceptions.py +0 -0
  33. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/__init__.py +0 -0
  34. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/__init__.py +0 -0
  35. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/evaluators.py +0 -0
  36. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/functions/__init__.py +0 -0
  37. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/functions/classify.py +0 -0
  38. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/functions/executor.py +0 -0
  39. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/functions/generate.py +0 -0
  40. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/functions/processing.py +0 -0
  41. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/__init__.py +0 -0
  42. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/anthropic.py +0 -0
  43. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/base.py +0 -0
  44. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/bedrock.py +0 -0
  45. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/litellm.py +0 -0
  46. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/openai.py +0 -0
  47. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/rate_limiters.py +0 -0
  48. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/vertex.py +0 -0
  49. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/models/vertexai.py +0 -0
  50. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/retrievals.py +0 -0
  51. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/templates/__init__.py +0 -0
  52. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/templates/default_templates.py +0 -0
  53. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/templates/template.py +0 -0
  54. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/utils/__init__.py +0 -0
  55. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/experimental/evals/utils/threads.py +0 -0
  56. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/README.md +0 -0
  57. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/__init__.py +0 -0
  58. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/binning.py +0 -0
  59. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/metrics.py +0 -0
  60. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/mixins.py +0 -0
  61. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  62. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/timeseries.py +0 -0
  63. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/metrics/wrappers.py +0 -0
  64. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/pointcloud/__init__.py +0 -0
  65. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/pointcloud/clustering.py +0 -0
  66. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  67. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/pointcloud/projectors.py +0 -0
  68. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  69. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/py.typed +0 -0
  70. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/__init__.py +0 -0
  71. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/__init__.py +0 -0
  72. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/context.py +0 -0
  73. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/helpers.py +0 -0
  74. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  75. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  76. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  77. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  78. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  79. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  80. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  81. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  82. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  83. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
  84. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/interceptor.py +0 -0
  85. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/routers/__init__.py +0 -0
  86. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/routers/evaluation_handler.py +0 -0
  87. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/routers/span_handler.py +0 -0
  88. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/routers/trace_handler.py +0 -0
  89. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/routers/utils.py +0 -0
  90. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/schema.py +0 -0
  91. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  92. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  93. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  94. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DatasetRole.py +0 -0
  95. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  96. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  97. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  98. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  99. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  100. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  101. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  102. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  103. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  104. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  105. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  106. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Event.py +0 -0
  107. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  108. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/ExportEventsMutation.py +0 -0
  109. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  110. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  111. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  112. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Model.py +0 -0
  113. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  114. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  115. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  116. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  117. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  118. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Segments.py +0 -0
  119. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  120. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/Span.py +0 -0
  121. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  122. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  123. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  124. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  125. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/__init__.py +0 -0
  126. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/node.py +0 -0
  127. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/api/types/pagination.py +0 -0
  128. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/app.py +0 -0
  129. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/main.py +0 -0
  130. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/prometheus.py +0 -0
  131. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  132. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  133. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  134. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  135. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  136. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  137. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  138. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  139. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/favicon.ico +0 -0
  140. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/index.css +0 -0
  141. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/static/modernizr.js +0 -0
  142. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/templates/__init__.py +0 -0
  143. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/templates/index.html +0 -0
  144. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/server/thread_server.py +0 -0
  145. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/services.py +0 -0
  146. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/session/__init__.py +0 -0
  147. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/session/client.py +0 -0
  148. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/session/data_extractor.py +0 -0
  149. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/session/evaluation.py +0 -0
  150. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/session/session.py +0 -0
  151. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/storage/__init__.py +0 -0
  152. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/storage/span_store/__init__.py +0 -0
  153. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/storage/span_store/text_file.py +0 -0
  154. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  155. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/dsl/filter.py +0 -0
  156. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  157. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/dsl/missing.py +0 -0
  158. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/dsl/query.py +0 -0
  159. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/errors.py +0 -0
  160. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  161. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/exporter.py +0 -0
  162. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/fixtures.py +0 -0
  163. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/langchain/__init__.py +0 -0
  164. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/langchain/instrumentor.py +0 -0
  165. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/llama_index/__init__.py +0 -0
  166. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/llama_index/callback.py +0 -0
  167. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/openai/__init__.py +0 -0
  168. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/openai/instrumentor.py +0 -0
  169. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/otel.py +0 -0
  170. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/projects.py +0 -0
  171. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/schemas.py +0 -0
  172. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/span_evaluations.py +0 -0
  173. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  174. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  175. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/trace_dataset.py +0 -0
  176. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/utils.py +0 -0
  177. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/v1/__init__.py +0 -0
  178. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  179. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  180. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/utilities/__init__.py +0 -0
  181. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/utilities/error_handling.py +0 -0
  182. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/utilities/logging.py +0 -0
  183. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/src/phoenix/utilities/project.py +0 -0
  184. {arize_phoenix-3.18.1 → arize_phoenix-3.19.0}/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: 3.18.1
3
+ Version: 3.19.0
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://docs.arize.com/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -20,6 +20,7 @@ Requires-Python: <3.13,>=3.8
20
20
  Requires-Dist: hdbscan>=0.8.33
21
21
  Requires-Dist: jinja2
22
22
  Requires-Dist: numpy
23
+ Requires-Dist: openinference-instrumentation
23
24
  Requires-Dist: openinference-instrumentation-langchain>=0.1.12
24
25
  Requires-Dist: openinference-instrumentation-llama-index>=1.2.0
25
26
  Requires-Dist: openinference-instrumentation-openai>=0.1.4
@@ -46,6 +46,7 @@ dependencies = [
46
46
  "opentelemetry-proto",
47
47
  "opentelemetry-exporter-otlp",
48
48
  "openinference-semantic-conventions>=0.1.5",
49
+ "openinference-instrumentation",
49
50
  "openinference-instrumentation-langchain>=0.1.12",
50
51
  "openinference-instrumentation-llama-index>=1.2.0",
51
52
  "openinference-instrumentation-openai>=0.1.4",
@@ -111,9 +111,20 @@ class Project:
111
111
  def add_eval(self, pb_eval: pb.Evaluation) -> None:
112
112
  self._evals.add(pb_eval)
113
113
 
114
+ def has_trace(self, trace_id: TraceID) -> bool:
115
+ return self._spans.has_trace(trace_id)
116
+
114
117
  def get_trace(self, trace_id: TraceID) -> Iterator[WrappedSpan]:
115
118
  yield from self._spans.get_trace(trace_id)
116
119
 
120
+ def get_trace_ids(
121
+ self,
122
+ start_time: Optional[datetime] = None,
123
+ stop_time: Optional[datetime] = None,
124
+ trace_ids: Optional[Iterable[TraceID]] = None,
125
+ ) -> Iterator[TraceID]:
126
+ yield from self._spans.get_trace_ids(start_time, stop_time, trace_ids)
127
+
117
128
  def get_spans(
118
129
  self,
119
130
  start_time: Optional[datetime] = None,
@@ -155,6 +166,21 @@ class Project:
155
166
  def right_open_time_range(self) -> Tuple[Optional[datetime], Optional[datetime]]:
156
167
  return self._spans.right_open_time_range
157
168
 
169
+ def get_trace_evaluation(self, trace_id: TraceID, name: str) -> Optional[pb.Evaluation]:
170
+ return self._evals.get_trace_evaluation(trace_id, name)
171
+
172
+ def get_trace_evaluation_names(self) -> List[EvaluationName]:
173
+ return self._evals.get_trace_evaluation_names()
174
+
175
+ def get_trace_evaluation_labels(self, name: EvaluationName) -> Tuple[str, ...]:
176
+ return self._evals.get_trace_evaluation_labels(name)
177
+
178
+ def get_trace_evaluation_trace_ids(self, name: EvaluationName) -> Tuple[TraceID, ...]:
179
+ return self._evals.get_trace_evaluation_trace_ids(name)
180
+
181
+ def get_evaluations_by_trace_id(self, trace_id: TraceID) -> List[pb.Evaluation]:
182
+ return self._evals.get_evaluations_by_trace_id(trace_id)
183
+
158
184
  def get_span_evaluation(self, span_id: SpanID, name: str) -> Optional[pb.Evaluation]:
159
185
  return self._evals.get_span_evaluation(span_id, name)
160
186
 
@@ -201,12 +227,43 @@ class Project:
201
227
  return self._is_archived
202
228
 
203
229
 
230
+ class _Trace:
231
+ def __init__(self, span: WrappedSpan) -> None:
232
+ self._trace_id: TraceID = span.context.trace_id
233
+ self._min_start_time: datetime = span.start_time
234
+ self._max_end_time: datetime = span.end_time
235
+ self._spans: List[WrappedSpan] = [span]
236
+
237
+ @property
238
+ def trace_id(self) -> TraceID:
239
+ return self._trace_id
240
+
241
+ @property
242
+ def start_time(self) -> datetime:
243
+ return self._min_start_time
244
+
245
+ @property
246
+ def latency_ms(self) -> float:
247
+ return (self._max_end_time - self._min_start_time).total_seconds() * 1000
248
+
249
+ def add(self, span: WrappedSpan) -> None:
250
+ self._min_start_time = min(self._min_start_time, span.start_time)
251
+ self._max_end_time = max(self._max_end_time, span.end_time)
252
+ self._spans.append(span)
253
+
254
+ def __eq__(self, other: Any) -> bool:
255
+ return self is other
256
+
257
+ def __iter__(self) -> Iterator[WrappedSpan]:
258
+ yield from self._spans
259
+
260
+
204
261
  class _Spans:
205
262
  def __init__(self) -> None:
206
263
  self._lock = RLock()
207
264
  self._spans: Dict[SpanID, WrappedSpan] = {}
208
265
  self._parent_span_ids: Dict[SpanID, _ParentSpanID] = {}
209
- self._traces: DefaultDict[TraceID, Set[WrappedSpan]] = defaultdict(set)
266
+ self._traces: Dict[TraceID, _Trace] = {}
210
267
  self._child_spans: DefaultDict[SpanID, Set[WrappedSpan]] = defaultdict(set)
211
268
  self._num_documents: DefaultDict[SpanID, int] = defaultdict(int)
212
269
  self._start_time_sorted_spans: SortedKeyList[WrappedSpan] = SortedKeyList(
@@ -221,12 +278,18 @@ class _Spans:
221
278
  (or will not arrive). For spans whose parent is not None, the root span status
222
279
  is temporary and will be revoked when its parent span arrives.
223
280
  """
224
- self._latency_sorted_root_spans: SortedKeyList[WrappedSpan] = SortedKeyList(
225
- key=lambda span: span[ComputedAttributes.LATENCY_MS],
281
+ self._latency_sorted_traces: SortedKeyList[_Trace] = SortedKeyList(
282
+ key=lambda trace: trace.latency_ms,
283
+ )
284
+ self._start_time_sorted_traces: SortedKeyList[_Trace] = SortedKeyList(
285
+ key=lambda trace: trace.start_time,
226
286
  )
227
287
  self._token_count_total: int = 0
228
288
  self._last_updated_at: Optional[datetime] = None
229
289
 
290
+ def has_trace(self, trace_id: TraceID) -> bool:
291
+ return trace_id in self._traces
292
+
230
293
  def get_trace(self, trace_id: TraceID) -> Iterator[WrappedSpan]:
231
294
  with self._lock:
232
295
  # make a copy because source data can mutate during iteration
@@ -236,6 +299,46 @@ class _Spans:
236
299
  for span in spans:
237
300
  yield span
238
301
 
302
+ def get_trace_ids(
303
+ self,
304
+ start_time: Optional[datetime] = None,
305
+ stop_time: Optional[datetime] = None,
306
+ trace_ids: Optional[Iterable[TraceID]] = None,
307
+ ) -> Iterator[TraceID]:
308
+ if not self._spans:
309
+ return
310
+ if start_time is None or stop_time is None:
311
+ min_start_time, max_stop_time = cast(
312
+ Tuple[datetime, datetime],
313
+ self.right_open_time_range,
314
+ )
315
+ start_time = start_time or min_start_time
316
+ stop_time = stop_time or max_stop_time
317
+ if trace_ids is not None:
318
+ with self._lock:
319
+ traces = tuple(
320
+ trace
321
+ for trace_id in trace_ids
322
+ if (
323
+ (trace := self._traces.get(trace_id))
324
+ and start_time <= trace.start_time < stop_time
325
+ )
326
+ )
327
+ else:
328
+ sorted_traces = self._start_time_sorted_traces
329
+ # make a copy because source data can mutate during iteration
330
+ with self._lock:
331
+ traces = tuple(
332
+ sorted_traces.irange_key(
333
+ start_time.astimezone(timezone.utc),
334
+ stop_time.astimezone(timezone.utc),
335
+ inclusive=(True, False),
336
+ reverse=True, # most recent traces first
337
+ )
338
+ )
339
+ for trace in traces:
340
+ yield trace.trace_id
341
+
239
342
  def get_spans(
240
343
  self,
241
344
  start_time: Optional[datetime] = None,
@@ -289,15 +392,15 @@ class _Spans:
289
392
  def root_span_latency_ms_quantiles(self, probability: float) -> Optional[float]:
290
393
  """Root span latency quantiles in milliseconds"""
291
394
  with self._lock:
292
- spans = self._latency_sorted_root_spans
293
- if not (n := len(spans)):
395
+ traces = self._latency_sorted_traces
396
+ if not (n := len(traces)):
294
397
  return None
295
398
  if probability >= 1:
296
- return cast(float, spans[-1][ComputedAttributes.LATENCY_MS])
399
+ return cast(float, traces[-1].latency_ms)
297
400
  if probability <= 0:
298
- return cast(float, spans[0][ComputedAttributes.LATENCY_MS])
401
+ return cast(float, traces[0].latency_ms)
299
402
  k = max(0, round(n * probability) - 1)
300
- return cast(float, spans[k][ComputedAttributes.LATENCY_MS])
403
+ return cast(float, traces[k].latency_ms)
301
404
 
302
405
  def get_descendant_spans(self, span_id: SpanID) -> Iterator[WrappedSpan]:
303
406
  for span in self._get_descendant_spans(span_id):
@@ -373,7 +476,6 @@ class _Spans:
373
476
  # A root span is a span whose parent span is not in our collection.
374
477
  # Now that their parent span has arrived, they are no longer root spans.
375
478
  self._start_time_sorted_root_spans.remove(child_span)
376
- self._latency_sorted_root_spans.remove(child_span)
377
479
 
378
480
  # Add computed attributes to span
379
481
  start_time = span.start_time
@@ -383,11 +485,10 @@ class _Spans:
383
485
 
384
486
  # Store the new span (after adding computed attributes)
385
487
  self._spans[span_id] = span
386
- self._traces[span.context.trace_id].add(span)
488
+ self._add_span_to_trace(span)
387
489
  self._start_time_sorted_spans.add(span)
388
490
  if parent_span_id is None or parent_span_id not in self._spans:
389
491
  self._start_time_sorted_root_spans.add(span)
390
- self._latency_sorted_root_spans.add(span)
391
492
  self._propagate_cumulative_values(span)
392
493
  self._update_cached_statistics(span)
393
494
 
@@ -395,6 +496,18 @@ class _Spans:
395
496
  # when they should refresh the page.
396
497
  self._last_updated_at = datetime.now(timezone.utc)
397
498
 
499
+ def _add_span_to_trace(self, span: WrappedSpan) -> None:
500
+ trace_id = span.context.trace_id
501
+ if (trace := self._traces.get(trace_id)) is None:
502
+ self._traces[trace_id] = trace = _Trace(span)
503
+ else:
504
+ # Must remove trace before mutating it.
505
+ self._latency_sorted_traces.remove(trace)
506
+ self._start_time_sorted_traces.remove(trace)
507
+ trace.add(span)
508
+ self._latency_sorted_traces.add(trace)
509
+ self._start_time_sorted_traces.add(trace)
510
+
398
511
  def _update_cached_statistics(self, span: WrappedSpan) -> None:
399
512
  # Update statistics for quick access later
400
513
  span_id = span.context.span_id
@@ -444,6 +557,7 @@ class _Evals:
444
557
  self._evaluations_by_trace_id: DefaultDict[TraceID, Dict[EvaluationName, pb.Evaluation]] = (
445
558
  defaultdict(dict)
446
559
  )
560
+ self._trace_evaluation_labels: DefaultDict[EvaluationName, Set[str]] = defaultdict(set)
447
561
  self._span_evaluations_by_name: DefaultDict[EvaluationName, Dict[SpanID, pb.Evaluation]] = (
448
562
  defaultdict(dict)
449
563
  )
@@ -484,6 +598,9 @@ class _Evals:
484
598
  trace_id = TraceID(subject_id.trace_id)
485
599
  self._evaluations_by_trace_id[trace_id][name] = evaluation
486
600
  self._trace_evaluations_by_name[name][trace_id] = evaluation
601
+ if evaluation.result.HasField("label"):
602
+ label = evaluation.result.label.value
603
+ self._trace_evaluation_labels[name].add(label)
487
604
  elif subject_id_kind is None:
488
605
  logger.warning(
489
606
  f"discarding evaluation with missing subject_id: {MessageToDict(evaluation)}"
@@ -496,6 +613,30 @@ class _Evals:
496
613
  def last_updated_at(self) -> Optional[datetime]:
497
614
  return self._last_updated_at
498
615
 
616
+ def get_trace_evaluation(self, trace_id: TraceID, name: str) -> Optional[pb.Evaluation]:
617
+ with self._lock:
618
+ trace_evaluations = self._evaluations_by_trace_id.get(trace_id)
619
+ return trace_evaluations.get(name) if trace_evaluations else None
620
+
621
+ def get_trace_evaluation_names(self) -> List[EvaluationName]:
622
+ with self._lock:
623
+ return list(self._trace_evaluations_by_name)
624
+
625
+ def get_trace_evaluation_labels(self, name: EvaluationName) -> Tuple[str, ...]:
626
+ with self._lock:
627
+ labels = self._trace_evaluation_labels.get(name)
628
+ return tuple(labels) if labels else ()
629
+
630
+ def get_trace_evaluation_trace_ids(self, name: EvaluationName) -> Tuple[TraceID, ...]:
631
+ with self._lock:
632
+ trace_evaluations = self._trace_evaluations_by_name.get(name)
633
+ return tuple(trace_evaluations.keys()) if trace_evaluations else ()
634
+
635
+ def get_evaluations_by_trace_id(self, trace_id: TraceID) -> List[pb.Evaluation]:
636
+ with self._lock:
637
+ evaluations = self._evaluations_by_trace_id.get(trace_id)
638
+ return list(evaluations.values()) if evaluations else []
639
+
499
640
  def get_span_evaluation(self, span_id: SpanID, name: str) -> Optional[pb.Evaluation]:
500
641
  with self._lock:
501
642
  span_evaluations = self._evaluations_by_span_id.get(span_id)
@@ -3,7 +3,7 @@ from typing import Optional
3
3
  import strawberry
4
4
 
5
5
  import phoenix.trace.v1 as pb
6
- from phoenix.trace.schemas import SpanID
6
+ from phoenix.trace.schemas import SpanID, TraceID
7
7
 
8
8
 
9
9
  @strawberry.interface
@@ -24,6 +24,26 @@ class Evaluation:
24
24
  )
25
25
 
26
26
 
27
+ @strawberry.type
28
+ class TraceEvaluation(Evaluation):
29
+ trace_id: strawberry.Private[TraceID]
30
+
31
+ @staticmethod
32
+ def from_pb_evaluation(evaluation: pb.Evaluation) -> "TraceEvaluation":
33
+ result = evaluation.result
34
+ score = result.score.value if result.HasField("score") else None
35
+ label = result.label.value if result.HasField("label") else None
36
+ explanation = result.explanation.value if result.HasField("explanation") else None
37
+ trace_id = TraceID(evaluation.subject_id.trace_id)
38
+ return TraceEvaluation(
39
+ name=evaluation.name,
40
+ score=score,
41
+ label=label,
42
+ explanation=explanation,
43
+ trace_id=trace_id,
44
+ )
45
+
46
+
27
47
  @strawberry.type
28
48
  class SpanEvaluation(Evaluation):
29
49
  span_id: strawberry.Private[SpanID]
@@ -19,6 +19,7 @@ from phoenix.server.api.types.pagination import (
19
19
  connection_from_list,
20
20
  )
21
21
  from phoenix.server.api.types.Span import Span, to_gql_span
22
+ from phoenix.server.api.types.Trace import Trace
22
23
  from phoenix.server.api.types.ValidationResult import ValidationResult
23
24
  from phoenix.trace.dsl import SpanFilter
24
25
  from phoenix.trace.schemas import SpanID, TraceID
@@ -69,6 +70,12 @@ class Project(Node):
69
70
  def latency_ms_p99(self) -> Optional[float]:
70
71
  return self.project.root_span_latency_ms_quantiles(0.99)
71
72
 
73
+ @strawberry.field
74
+ def trace(self, trace_id: ID) -> Optional[Trace]:
75
+ if self.project.has_trace(TraceID(trace_id)):
76
+ return Trace(trace_id=trace_id, project=self.project)
77
+ return None
78
+
72
79
  @strawberry.field
73
80
  def spans(
74
81
  self,
@@ -88,7 +95,12 @@ class Project(Node):
88
95
  last=last,
89
96
  before=before if isinstance(before, Cursor) else None,
90
97
  )
91
- if not (project := self.project).span_count():
98
+ start_time = time_range.start if time_range else None
99
+ stop_time = time_range.end if time_range else None
100
+ if not (project := self.project).span_count(
101
+ start_time=start_time,
102
+ stop_time=stop_time,
103
+ ):
92
104
  return connection_from_list(data=[], args=args)
93
105
  predicate = (
94
106
  SpanFilter(
@@ -100,8 +112,8 @@ class Project(Node):
100
112
  )
101
113
  if not trace_ids:
102
114
  spans = project.get_spans(
103
- start_time=time_range.start if time_range else None,
104
- stop_time=time_range.end if time_range else None,
115
+ start_time=start_time,
116
+ stop_time=stop_time,
105
117
  root_spans_only=root_spans_only,
106
118
  )
107
119
  else:
@@ -115,6 +127,13 @@ class Project(Node):
115
127
  data = [to_gql_span(span, project) for span in spans]
116
128
  return connection_from_list(data=data, args=args)
117
129
 
130
+ @strawberry.field(
131
+ description="Names of all available evaluations for traces. "
132
+ "(The list contains no duplicates.)"
133
+ ) # type: ignore
134
+ def trace_evaluation_names(self) -> List[str]:
135
+ return self.project.get_trace_evaluation_names()
136
+
118
137
  @strawberry.field(
119
138
  description="Names of all available evaluations for spans. "
120
139
  "(The list contains no duplicates.)"
@@ -133,6 +152,37 @@ class Project(Node):
133
152
  None if span_id is UNSET else SpanID(span_id),
134
153
  )
135
154
 
155
+ @strawberry.field
156
+ def trace_evaluation_summary(
157
+ self,
158
+ evaluation_name: str,
159
+ time_range: Optional[TimeRange] = UNSET,
160
+ ) -> Optional[EvaluationSummary]:
161
+ project = self.project
162
+ eval_trace_ids = project.get_trace_evaluation_trace_ids(evaluation_name)
163
+ if not eval_trace_ids:
164
+ return None
165
+ trace_ids = project.get_trace_ids(
166
+ start_time=time_range.start if time_range else None,
167
+ stop_time=time_range.end if time_range else None,
168
+ trace_ids=eval_trace_ids,
169
+ )
170
+ evaluations = tuple(
171
+ evaluation
172
+ for trace_id in trace_ids
173
+ if (
174
+ evaluation := project.get_trace_evaluation(
175
+ trace_id,
176
+ evaluation_name,
177
+ )
178
+ )
179
+ is not None
180
+ )
181
+ if not evaluations:
182
+ return None
183
+ labels = project.get_trace_evaluation_labels(evaluation_name)
184
+ return EvaluationSummary(evaluations, labels)
185
+
136
186
  @strawberry.field
137
187
  def span_evaluation_summary(
138
188
  self,
@@ -0,0 +1,47 @@
1
+ from typing import List, Optional
2
+
3
+ import strawberry
4
+ from strawberry import ID, UNSET, Private
5
+
6
+ from phoenix.core.project import Project
7
+ from phoenix.server.api.types.Evaluation import TraceEvaluation
8
+ from phoenix.server.api.types.pagination import (
9
+ Connection,
10
+ ConnectionArgs,
11
+ Cursor,
12
+ connection_from_list,
13
+ )
14
+ from phoenix.server.api.types.Span import Span, to_gql_span
15
+ from phoenix.trace.schemas import TraceID
16
+
17
+
18
+ @strawberry.type
19
+ class Trace:
20
+ trace_id: ID
21
+ project: Private[Project]
22
+
23
+ @strawberry.field
24
+ def spans(
25
+ self,
26
+ first: Optional[int] = 50,
27
+ last: Optional[int] = UNSET,
28
+ after: Optional[Cursor] = UNSET,
29
+ before: Optional[Cursor] = UNSET,
30
+ ) -> Connection[Span]:
31
+ args = ConnectionArgs(
32
+ first=first,
33
+ after=after if isinstance(after, Cursor) else None,
34
+ last=last,
35
+ before=before if isinstance(before, Cursor) else None,
36
+ )
37
+ spans = sorted(
38
+ self.project.get_trace(TraceID(self.trace_id)),
39
+ key=lambda span: span.start_time,
40
+ )
41
+ data = [to_gql_span(span, self.project) for span in spans]
42
+ return connection_from_list(data=data, args=args)
43
+
44
+ @strawberry.field(description="Evaluations associated with the trace") # type: ignore
45
+ def trace_evaluations(self) -> List[TraceEvaluation]:
46
+ evaluations = self.project.get_evaluations_by_trace_id(TraceID(self.trace_id))
47
+ return [TraceEvaluation.from_pb_evaluation(evaluation) for evaluation in evaluations]