arize-phoenix 8.22.1__tar.gz → 8.24.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 (379) hide show
  1. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/PKG-INFO +22 -2
  2. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/README.md +21 -1
  3. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/config.py +65 -3
  4. arize_phoenix-8.24.0/src/phoenix/db/facilitator.py +188 -0
  5. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/helpers.py +16 -0
  6. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/context.py +2 -0
  7. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/user_mutations.py +10 -0
  8. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/queries.py +3 -14
  9. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/__init__.py +2 -0
  10. arize_phoenix-8.24.0/src/phoenix/server/api/routers/v1/projects.py +393 -0
  11. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/subscriptions.py +1 -1
  12. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/app.py +17 -0
  13. arize_phoenix-8.24.0/src/phoenix/server/email/sender.py +124 -0
  14. arize_phoenix-8.24.0/src/phoenix/server/email/templates/welcome.html +12 -0
  15. arize_phoenix-8.24.0/src/phoenix/server/email/types.py +26 -0
  16. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/main.py +8 -1
  17. arize_phoenix-8.24.0/src/phoenix/server/static/.vite/manifest.json +87 -0
  18. arize_phoenix-8.22.1/src/phoenix/server/static/assets/components-BAc4OPED.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/components-B6cljCxu.js +82 -82
  19. arize_phoenix-8.22.1/src/phoenix/server/static/assets/index-Du53xkjY.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/index-DfHKoAV9.js +2 -2
  20. arize_phoenix-8.22.1/src/phoenix/server/static/assets/pages-Dz-gbBPF.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/pages-Dhitcl5V.js +342 -339
  21. arize_phoenix-8.22.1/src/phoenix/server/static/assets/vendor-CEisxXSv.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/vendor-C3H3sezv.js +1 -1
  22. arize_phoenix-8.22.1/src/phoenix/server/static/assets/vendor-arizeai-BCTsSnvS.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/vendor-arizeai-DT8pwHfH.js +1 -1
  23. arize_phoenix-8.22.1/src/phoenix/server/static/assets/vendor-codemirror-DIWnRs_7.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/vendor-codemirror-DvimrGxD.js +1 -1
  24. arize_phoenix-8.22.1/src/phoenix/server/static/assets/vendor-recharts-Bame54mG.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/vendor-recharts-DuSQBcYW.js +1 -1
  25. arize_phoenix-8.22.1/src/phoenix/server/static/assets/vendor-shiki-Cc73E4D-.js → arize_phoenix-8.24.0/src/phoenix/server/static/assets/vendor-shiki-i05Hmswh.js +1 -1
  26. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/session/session.py +10 -0
  27. arize_phoenix-8.24.0/src/phoenix/version.py +1 -0
  28. arize_phoenix-8.22.1/src/phoenix/db/facilitator.py +0 -155
  29. arize_phoenix-8.22.1/src/phoenix/server/email/sender.py +0 -97
  30. arize_phoenix-8.22.1/src/phoenix/server/email/types.py +0 -11
  31. arize_phoenix-8.22.1/src/phoenix/server/static/.vite/manifest.json +0 -87
  32. arize_phoenix-8.22.1/src/phoenix/version.py +0 -1
  33. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/.gitignore +0 -0
  34. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/IP_NOTICE +0 -0
  35. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/LICENSE +0 -0
  36. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/pyproject.toml +0 -0
  37. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/__init__.py +0 -0
  38. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/auth.py +0 -0
  39. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/core/__init__.py +0 -0
  40. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/core/embedding_dimension.py +0 -0
  41. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/core/model.py +0 -0
  42. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/core/model_schema.py +0 -0
  43. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  44. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/datetime_utils.py +0 -0
  45. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/README.md +0 -0
  46. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/__init__.py +0 -0
  47. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/alembic.ini +0 -0
  48. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/bulk_inserter.py +0 -0
  49. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/engines.py +0 -0
  50. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/enums.py +0 -0
  51. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/__init__.py +0 -0
  52. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/constants.py +0 -0
  53. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/dataset.py +0 -0
  54. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/document_annotation.py +0 -0
  55. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/evaluation.py +0 -0
  56. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/helpers.py +0 -0
  57. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/span.py +0 -0
  58. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/span_annotation.py +0 -0
  59. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/trace_annotation.py +0 -0
  60. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/insertion/types.py +0 -0
  61. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrate.py +0 -0
  62. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/__init__.py +0 -0
  63. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/data_migration_scripts/__init__.py +0 -0
  64. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/data_migration_scripts/populate_project_sessions.py +0 -0
  65. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/env.py +0 -0
  66. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/script.py.mako +0 -0
  67. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  68. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +0 -0
  69. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/versions/4ded9e43755f_create_project_sessions_table.py +0 -0
  70. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/versions/bc8fea3c2bc8_add_prompt_tables.py +0 -0
  71. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/versions/cd164e83824f_users_and_tokens.py +0 -0
  72. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  73. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/models.py +0 -0
  74. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/types/__init__.py +0 -0
  75. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/types/identifier.py +0 -0
  76. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/db/types/model_provider.py +0 -0
  77. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/exceptions.py +0 -0
  78. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/__init__.py +0 -0
  79. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  80. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/evaluators/base.py +0 -0
  81. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  82. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  83. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
  84. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/functions.py +0 -0
  85. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/tracing.py +0 -0
  86. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/types.py +0 -0
  87. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/experiments/utils.py +0 -0
  88. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/inferences/__init__.py +0 -0
  89. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/inferences/errors.py +0 -0
  90. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/inferences/fixtures.py +0 -0
  91. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/inferences/inferences.py +0 -0
  92. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/inferences/schema.py +0 -0
  93. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/inferences/validation.py +0 -0
  94. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/logging/__init__.py +0 -0
  95. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/logging/_config.py +0 -0
  96. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/logging/_filter.py +0 -0
  97. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/logging/_formatter.py +0 -0
  98. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/README.md +0 -0
  99. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/__init__.py +0 -0
  100. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/binning.py +0 -0
  101. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/metrics.py +0 -0
  102. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/mixins.py +0 -0
  103. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  104. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/timeseries.py +0 -0
  105. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/metrics/wrappers.py +0 -0
  106. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/pointcloud/__init__.py +0 -0
  107. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/pointcloud/clustering.py +0 -0
  108. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  109. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/pointcloud/projectors.py +0 -0
  110. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  111. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/py.typed +0 -0
  112. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/__init__.py +0 -0
  113. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/README.md +0 -0
  114. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/__init__.py +0 -0
  115. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/auth.py +0 -0
  116. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/__init__.py +0 -0
  117. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  118. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  119. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  120. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  121. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  122. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  123. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  124. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  125. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  126. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  127. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  128. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/experiment_run_annotations.py +0 -0
  129. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  130. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  131. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  132. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  133. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/num_child_spans.py +0 -0
  134. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/num_spans_per_trace.py +0 -0
  135. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  136. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/prompt_version_sequence_number.py +0 -0
  137. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  138. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/session_io.py +0 -0
  139. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/session_num_traces.py +0 -0
  140. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/session_num_traces_with_error.py +0 -0
  141. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/session_token_usages.py +0 -0
  142. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/session_trace_latency_ms_quantile.py +0 -0
  143. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  144. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/span_by_id.py +0 -0
  145. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  146. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  147. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  148. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/table_fields.py +0 -0
  149. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  150. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/trace_by_trace_ids.py +0 -0
  151. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/trace_root_spans.py +0 -0
  152. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/user_roles.py +0 -0
  153. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/dataloaders/users.py +0 -0
  154. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/exceptions.py +0 -0
  155. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
  156. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  157. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/experiment_run_filters.py +0 -0
  158. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/playground_clients.py +0 -0
  159. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/playground_registry.py +0 -0
  160. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/playground_spans.py +0 -0
  161. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/prompts/__init__.py +0 -0
  162. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/prompts/conversions/__init__.py +0 -0
  163. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/prompts/conversions/anthropic.py +0 -0
  164. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/prompts/conversions/openai.py +0 -0
  165. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/helpers/prompts/models.py +0 -0
  166. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  167. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  168. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/ChatCompletionInput.py +0 -0
  169. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/ChatCompletionMessageInput.py +0 -0
  170. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  171. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  172. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  173. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  174. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  175. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  176. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  177. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  178. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  179. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  180. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  181. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  182. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  183. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  184. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  185. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  186. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/GenerativeModelInput.py +0 -0
  187. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  188. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/InvocationParameters.py +0 -0
  189. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  190. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  191. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  192. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  193. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/ProjectSessionSort.py +0 -0
  194. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/PromptTemplateOptions.py +0 -0
  195. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/PromptVersionInput.py +0 -0
  196. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  197. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  198. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  199. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  200. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/UserRoleInput.py +0 -0
  201. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
  202. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/interceptor.py +0 -0
  203. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/__init__.py +0 -0
  204. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/api_key_mutations.py +0 -0
  205. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/chat_mutations.py +0 -0
  206. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
  207. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
  208. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  209. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
  210. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/prompt_label_mutations.py +0 -0
  211. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/prompt_mutations.py +0 -0
  212. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/prompt_version_tag_mutations.py +0 -0
  213. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +0 -0
  214. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +0 -0
  215. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/mutations/trace_mutations.py +0 -0
  216. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/openapi/__init__.py +0 -0
  217. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/openapi/main.py +0 -0
  218. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/openapi/schema.py +0 -0
  219. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/__init__.py +0 -0
  220. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/auth.py +0 -0
  221. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/embeddings.py +0 -0
  222. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/oauth2.py +0 -0
  223. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/utils.py +0 -0
  224. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/datasets.py +0 -0
  225. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  226. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -0
  227. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -0
  228. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/experiments.py +0 -0
  229. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/models.py +0 -0
  230. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/prompts.py +0 -0
  231. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/spans.py +0 -0
  232. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/traces.py +0 -0
  233. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  234. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/schema.py +0 -0
  235. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Annotation.py +0 -0
  236. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  237. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  238. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ApiKey.py +0 -0
  239. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/AuthMethod.py +0 -0
  240. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ChatCompletionMessageRole.py +0 -0
  241. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +0 -0
  242. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  243. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  244. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  245. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  246. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  247. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  248. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  249. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  250. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  251. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  252. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  253. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  254. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  255. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  256. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  257. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  258. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  259. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
  260. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  261. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Event.py +0 -0
  262. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  263. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  264. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Experiment.py +0 -0
  265. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  266. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  267. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
  268. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  269. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  270. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  271. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/GenerativeModel.py +0 -0
  272. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/GenerativeProvider.py +0 -0
  273. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Identifier.py +0 -0
  274. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Inferences.py +0 -0
  275. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  276. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  277. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  278. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Model.py +0 -0
  279. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  280. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  281. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Project.py +0 -0
  282. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ProjectSession.py +0 -0
  283. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Prompt.py +0 -0
  284. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/PromptLabel.py +0 -0
  285. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  286. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/PromptVersion.py +0 -0
  287. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/PromptVersionTag.py +0 -0
  288. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/PromptVersionTemplate.py +0 -0
  289. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ResponseFormat.py +0 -0
  290. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  291. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  292. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Segments.py +0 -0
  293. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  294. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Span.py +0 -0
  295. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  296. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/SpanIOValue.py +0 -0
  297. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/SystemApiKey.py +0 -0
  298. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  299. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/TokenUsage.py +0 -0
  300. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ToolDefinition.py +0 -0
  301. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/Trace.py +0 -0
  302. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  303. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  304. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/User.py +0 -0
  305. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/UserApiKey.py +0 -0
  306. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/UserRole.py +0 -0
  307. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  308. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  309. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/__init__.py +0 -0
  310. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/node.py +0 -0
  311. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/types/pagination.py +0 -0
  312. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/api/utils.py +0 -0
  313. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/bearer_auth.py +0 -0
  314. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/dml_event.py +0 -0
  315. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/dml_event_handler.py +0 -0
  316. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/email/__init__.py +0 -0
  317. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/email/templates/__init__.py +0 -0
  318. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/email/templates/password_reset.html +0 -0
  319. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/grpc_server.py +0 -0
  320. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/jwt_store.py +0 -0
  321. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/oauth2.py +0 -0
  322. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/openapi/__init__.py +0 -0
  323. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/prometheus.py +0 -0
  324. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/rate_limiters.py +0 -0
  325. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  326. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  327. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  328. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  329. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  330. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  331. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  332. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  333. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/assets/vendor-Cg6lcjUC.css +0 -0
  334. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/assets/vendor-three-C5WAXd5r.js +0 -0
  335. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/favicon.ico +0 -0
  336. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/static/modernizr.js +0 -0
  337. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/telemetry.py +0 -0
  338. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/templates/__init__.py +0 -0
  339. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/templates/index.html +0 -0
  340. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/thread_server.py +0 -0
  341. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/server/types.py +0 -0
  342. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/services.py +0 -0
  343. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/session/__init__.py +0 -0
  344. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/session/client.py +0 -0
  345. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/session/data_extractor.py +0 -0
  346. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/session/evaluation.py +0 -0
  347. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/settings.py +0 -0
  348. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/__init__.py +0 -0
  349. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/attributes.py +0 -0
  350. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/dsl/README.md +0 -0
  351. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  352. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/dsl/filter.py +0 -0
  353. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  354. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/dsl/query.py +0 -0
  355. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/errors.py +0 -0
  356. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  357. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/exporter.py +0 -0
  358. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/fixtures.py +0 -0
  359. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/otel.py +0 -0
  360. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/projects.py +0 -0
  361. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/schemas.py +0 -0
  362. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/span_evaluations.py +0 -0
  363. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  364. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  365. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/trace_dataset.py +0 -0
  366. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/utils.py +0 -0
  367. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/v1/__init__.py +0 -0
  368. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  369. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  370. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/__init__.py +0 -0
  371. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/client.py +0 -0
  372. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/deprecation.py +0 -0
  373. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/error_handling.py +0 -0
  374. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/json.py +0 -0
  375. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/logging.py +0 -0
  376. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/project.py +0 -0
  377. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/re.py +0 -0
  378. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/span_store.py +0 -0
  379. {arize_phoenix-8.22.1 → arize_phoenix-8.24.0}/src/phoenix/utilities/template_formatters.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 8.22.1
3
+ Version: 8.24.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
@@ -141,7 +141,10 @@ Description-Content-Type: text/markdown
141
141
  <a target="_blank" href="https://arize-ai.slack.com/join/shared_invite/zt-11t1vbu4x-xkBIHmOREQnYnYDH1GDfCg?__hstc=259489365.a667dfafcfa0169c8aee4178d115dc81.1733501603539.1733501603539.1733501603539.1&__hssc=259489365.1.1733501603539&__hsfp=3822854628&submissionGuid=381a0676-8f38-437b-96f2-fc10875658df#/shared-invite/email">
142
142
  <img src="https://img.shields.io/static/v1?message=Community&logo=slack&labelColor=grey&color=blue&logoColor=white&label=%20"/>
143
143
  </a>
144
- <a target="_blank" href="https://twitter.com/ArizePhoenix">
144
+ <a target="_blank" href="https://bsky.app/profile/arize-phoenix.bsky.social">
145
+ <img src="https://img.shields.io/badge/-phoenix-blue.svg?color=blue&labelColor=gray&logo=bluesky">
146
+ </a>
147
+ <a target="_blank" href="https://x.com/ArizePhoenix">
145
148
  <img src="https://img.shields.io/badge/-ArizePhoenix-blue.svg?color=blue&labelColor=gray&logo=x">
146
149
  </a>
147
150
  <a target="_blank" href="https://pypi.org/project/arize-phoenix/">
@@ -156,6 +159,9 @@ Description-Content-Type: text/markdown
156
159
  <a target="_blank" href="https://hub.docker.com/r/arizephoenix/phoenix/tags">
157
160
  <img src="https://img.shields.io/docker/v/arizephoenix/phoenix?sort=semver&logo=docker&label=image&color=blue">
158
161
  </a>
162
+ <a target="_blank" href="https://github.com/Arize-ai/phoenix/tree/main/js/packages/phoenix-mcp">
163
+ <img src="https://badge.mcpx.dev?status=on" title="MCP Enabled"/>
164
+ </a>
159
165
  </p>
160
166
 
161
167
  Phoenix is an open-source AI observability platform designed for experimentation, evaluation, and troubleshooting. It provides:
@@ -181,6 +187,20 @@ pip install arize-phoenix
181
187
 
182
188
  Phoenix container images are available via [Docker Hub](https://hub.docker.com/r/arizephoenix/phoenix) and can be deployed using Docker or Kubernetes.
183
189
 
190
+ ## Packages
191
+
192
+ The `arize-phoenix` package includes the entire Phoenix platfom. However if you have deployed the Phoenix platform, there are light-weight Python sub-packages and TypeScript packages that can be used in conjunction with the platfrom.
193
+
194
+ ### Subpackages
195
+
196
+ | Package | Language | Description |
197
+ | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
198
+ | [arize-phoenix-otel](https://github.com/Arize-ai/phoenix/tree/main/packages/phoenix-otel) | Python [![PyPI Version](https://img.shields.io/pypi/v/arize-phoenix-otel)](https://pypi.org/project/arize-phoenix-otel/) | Provides a lightweight wrapper around OpenTelemetry primitives with Phoenix-aware defaults |
199
+ | [arize-phoenix-client](https://github.com/Arize-ai/phoenix/tree/main/packages/phoenix-client) | Python [![PyPI Version](https://img.shields.io/pypi/v/arize-phoenix-client)](https://pypi.org/project/arize-phoenix-client/) | Lightweight client for interacting with the Phoenix server via its OpenAPI REST interface |
200
+ | [arize-phoenix-evals](https://github.com/Arize-ai/phoenix/tree/main/packages/phoenix-evals) | Python [![PyPI Version](https://img.shields.io/pypi/v/arize-phoenix-evals)](https://pypi.org/project/arize-phoenix-evals/) | Tooling to evaluate LLM applications including RAG relevance, answer relevance, and more |
201
+ | [@arizeai/phoenix-client](https://github.com/Arize-ai/phoenix/tree/main/js/packages/phoenix-client) | JavaScript [![NPM Version](https://img.shields.io/npm/v/%40arizeai%2Fphoenix-client)](https://www.npmjs.com/package/@arizeai/phoenix-client) | Client for the Arize Phoenix API |
202
+ | [@arizeai/phoenix-mcp](https://github.com/Arize-ai/phoenix/tree/main/js/packages/phoenix-mcp) | JavaScript [![NPM Version](https://img.shields.io/npm/v/%40arizeai%2Fphoenix-mcp)](https://www.npmjs.com/package/@arizeai/phoenix-mcp) | MCP server implementation for Arize Phoenix providing unified interface to Phoenix's capabilities |
203
+
184
204
  ## Tracing Integrations
185
205
 
186
206
  Phoenix is built on top of OpenTelemetry and is vendor, language, and framework agnostic. For details about tracing integrations and example applications, see the [OpenInference](https://github.com/Arize-ai/openinference) project.
@@ -10,7 +10,10 @@
10
10
  <a target="_blank" href="https://arize-ai.slack.com/join/shared_invite/zt-11t1vbu4x-xkBIHmOREQnYnYDH1GDfCg?__hstc=259489365.a667dfafcfa0169c8aee4178d115dc81.1733501603539.1733501603539.1733501603539.1&__hssc=259489365.1.1733501603539&__hsfp=3822854628&submissionGuid=381a0676-8f38-437b-96f2-fc10875658df#/shared-invite/email">
11
11
  <img src="https://img.shields.io/static/v1?message=Community&logo=slack&labelColor=grey&color=blue&logoColor=white&label=%20"/>
12
12
  </a>
13
- <a target="_blank" href="https://twitter.com/ArizePhoenix">
13
+ <a target="_blank" href="https://bsky.app/profile/arize-phoenix.bsky.social">
14
+ <img src="https://img.shields.io/badge/-phoenix-blue.svg?color=blue&labelColor=gray&logo=bluesky">
15
+ </a>
16
+ <a target="_blank" href="https://x.com/ArizePhoenix">
14
17
  <img src="https://img.shields.io/badge/-ArizePhoenix-blue.svg?color=blue&labelColor=gray&logo=x">
15
18
  </a>
16
19
  <a target="_blank" href="https://pypi.org/project/arize-phoenix/">
@@ -25,6 +28,9 @@
25
28
  <a target="_blank" href="https://hub.docker.com/r/arizephoenix/phoenix/tags">
26
29
  <img src="https://img.shields.io/docker/v/arizephoenix/phoenix?sort=semver&logo=docker&label=image&color=blue">
27
30
  </a>
31
+ <a target="_blank" href="https://github.com/Arize-ai/phoenix/tree/main/js/packages/phoenix-mcp">
32
+ <img src="https://badge.mcpx.dev?status=on" title="MCP Enabled"/>
33
+ </a>
28
34
  </p>
29
35
 
30
36
  Phoenix is an open-source AI observability platform designed for experimentation, evaluation, and troubleshooting. It provides:
@@ -50,6 +56,20 @@ pip install arize-phoenix
50
56
 
51
57
  Phoenix container images are available via [Docker Hub](https://hub.docker.com/r/arizephoenix/phoenix) and can be deployed using Docker or Kubernetes.
52
58
 
59
+ ## Packages
60
+
61
+ The `arize-phoenix` package includes the entire Phoenix platfom. However if you have deployed the Phoenix platform, there are light-weight Python sub-packages and TypeScript packages that can be used in conjunction with the platfrom.
62
+
63
+ ### Subpackages
64
+
65
+ | Package | Language | Description |
66
+ | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
67
+ | [arize-phoenix-otel](https://github.com/Arize-ai/phoenix/tree/main/packages/phoenix-otel) | Python [![PyPI Version](https://img.shields.io/pypi/v/arize-phoenix-otel)](https://pypi.org/project/arize-phoenix-otel/) | Provides a lightweight wrapper around OpenTelemetry primitives with Phoenix-aware defaults |
68
+ | [arize-phoenix-client](https://github.com/Arize-ai/phoenix/tree/main/packages/phoenix-client) | Python [![PyPI Version](https://img.shields.io/pypi/v/arize-phoenix-client)](https://pypi.org/project/arize-phoenix-client/) | Lightweight client for interacting with the Phoenix server via its OpenAPI REST interface |
69
+ | [arize-phoenix-evals](https://github.com/Arize-ai/phoenix/tree/main/packages/phoenix-evals) | Python [![PyPI Version](https://img.shields.io/pypi/v/arize-phoenix-evals)](https://pypi.org/project/arize-phoenix-evals/) | Tooling to evaluate LLM applications including RAG relevance, answer relevance, and more |
70
+ | [@arizeai/phoenix-client](https://github.com/Arize-ai/phoenix/tree/main/js/packages/phoenix-client) | JavaScript [![NPM Version](https://img.shields.io/npm/v/%40arizeai%2Fphoenix-client)](https://www.npmjs.com/package/@arizeai/phoenix-client) | Client for the Arize Phoenix API |
71
+ | [@arizeai/phoenix-mcp](https://github.com/Arize-ai/phoenix/tree/main/js/packages/phoenix-mcp) | JavaScript [![NPM Version](https://img.shields.io/npm/v/%40arizeai%2Fphoenix-mcp)](https://www.npmjs.com/package/@arizeai/phoenix-mcp) | MCP server implementation for Arize Phoenix providing unified interface to Phoenix's capabilities |
72
+
53
73
  ## Tracing Integrations
54
74
 
55
75
  Phoenix is built on top of OpenTelemetry and is vendor, language, and framework agnostic. For details about tracing integrations and example applications, see the [OpenInference](https://github.com/Arize-ai/openinference) project.
@@ -8,10 +8,11 @@ from enum import Enum
8
8
  from importlib.metadata import version
9
9
  from pathlib import Path
10
10
  from typing import Any, Optional, Union, cast, overload
11
- from urllib.parse import quote_plus, urlparse
11
+ from urllib.parse import quote_plus, urljoin, urlparse
12
12
 
13
13
  import wrapt
14
14
  from email_validator import EmailNotValidError, validate_email
15
+ from starlette.datastructures import URL
15
16
 
16
17
  from phoenix.utilities.logging import log_a_list
17
18
 
@@ -182,6 +183,19 @@ If the username or email address already exists in the database, the user record
182
183
  modified, e.g., changed from non-admin to admin. Changing this environment variable for the next
183
184
  startup will not undo any records created in previous startups.
184
185
  """
186
+ ENV_PHOENIX_ROOT_URL = "PHOENIX_ROOT_URL"
187
+ """
188
+ This is the full URL used to access Phoenix from a web browser. This setting is important when
189
+ you have a reverse proxy in front of Phoenix. If the reverse proxy exposes Phoenix through a
190
+ sub-path, add that sub-path to the end of this URL setting.
191
+
192
+ WARNING: When a sub-path is needed, you must also specify the sub-path via the environment
193
+ variable PHOENIX_HOST_ROOT_PATH. Setting just this URL setting is not enough.
194
+
195
+ Examples:
196
+ - With a sub-path: "https://example.com/phoenix"
197
+ - Without a sub-path: "https://phoenix.example.com"
198
+ """
185
199
 
186
200
 
187
201
  # SMTP settings
@@ -209,7 +223,11 @@ ENV_PHOENIX_SMTP_VALIDATE_CERTS = "PHOENIX_SMTP_VALIDATE_CERTS"
209
223
  """
210
224
  Whether to validate SMTP server certificates. Defaults to true.
211
225
  """
212
-
226
+ ENV_PHOENIX_ALLOWED_ORIGINS = "PHOENIX_ALLOWED_ORIGINS"
227
+ """
228
+ List of allowed origins for CORS. Defaults to None.
229
+ When set to None, CORS is disabled.
230
+ """
213
231
  # API extension settings
214
232
  ENV_PHOENIX_FASTAPI_MIDDLEWARE_PATHS = "PHOENIX_FASTAPI_MIDDLEWARE_PATHS"
215
233
  ENV_PHOENIX_GQL_EXTENSION_PATHS = "PHOENIX_GQL_EXTENSION_PATHS"
@@ -824,7 +842,7 @@ def get_env_host() -> str:
824
842
 
825
843
 
826
844
  def get_env_host_root_path() -> str:
827
- if (host_root_path := getenv(ENV_PHOENIX_HOST_ROOT_PATH)) is None:
845
+ if not (host_root_path := getenv(ENV_PHOENIX_HOST_ROOT_PATH)):
828
846
  return HOST_ROOT_PATH
829
847
  if not host_root_path.startswith("/"):
830
848
  raise ValueError(
@@ -890,7 +908,33 @@ def get_env_client_headers() -> dict[str, str]:
890
908
  return headers
891
909
 
892
910
 
911
+ def get_env_root_url() -> URL:
912
+ """
913
+ Get the URL used to access Phoenix from a web browser
914
+
915
+ Returns:
916
+ URL: The root URL of the Phoenix server
917
+
918
+ Note:
919
+ This is intended to replace the legacy `get_base_url()` helper function. In
920
+ particular, `get_env_collector_endpoint()` is really for the client and should be
921
+ deprecated on the server side.
922
+ """
923
+ if root_url := getenv(ENV_PHOENIX_ROOT_URL):
924
+ result = urlparse(root_url)
925
+ if not result.scheme or not result.netloc:
926
+ raise ValueError(
927
+ f"The environment variable `{ENV_PHOENIX_ROOT_URL}` must be a valid URL."
928
+ )
929
+ return URL(root_url)
930
+ host = get_env_host()
931
+ if host == "0.0.0.0":
932
+ host = "127.0.0.1"
933
+ return URL(urljoin(f"http://{host}:{get_env_port()}", get_env_host_root_path()))
934
+
935
+
893
936
  def get_base_url() -> str:
937
+ """Deprecated: Use get_env_root_url() instead, but note the difference in behavior."""
894
938
  host = get_env_host()
895
939
  if host == "0.0.0.0":
896
940
  host = "127.0.0.1"
@@ -1049,4 +1093,22 @@ def get_env_disable_migrations() -> bool:
1049
1093
  DEFAULT_PROJECT_NAME = "default"
1050
1094
  _KUBERNETES_PHOENIX_PORT_PATTERN = re.compile(r"^tcp://\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}:\d+$")
1051
1095
 
1096
+
1097
+ def get_env_allowed_origins() -> Optional[list[str]]:
1098
+ """
1099
+ Gets the value of the PHOENIX_ALLOWED_ORIGINS environment variable.
1100
+ """
1101
+ allowed_origins = getenv(ENV_PHOENIX_ALLOWED_ORIGINS)
1102
+ if allowed_origins is None:
1103
+ return None
1104
+
1105
+ return allowed_origins.split(",")
1106
+
1107
+
1108
+ def verify_server_environment_variables() -> None:
1109
+ """Verify that the environment variables are set correctly. Raises an error otherwise."""
1110
+ get_env_root_url()
1111
+
1112
+
1052
1113
  SKLEARN_VERSION = cast(tuple[int, int], tuple(map(int, version("scikit-learn").split(".", 2)[:2])))
1114
+ PLAYGROUND_PROJECT_NAME = "playground"
@@ -0,0 +1,188 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ import secrets
6
+ from asyncio import gather
7
+ from functools import partial
8
+ from typing import Optional
9
+
10
+ from sqlalchemy import (
11
+ distinct,
12
+ insert,
13
+ select,
14
+ )
15
+
16
+ from phoenix.auth import (
17
+ DEFAULT_ADMIN_EMAIL,
18
+ DEFAULT_ADMIN_USERNAME,
19
+ DEFAULT_SECRET_LENGTH,
20
+ DEFAULT_SYSTEM_EMAIL,
21
+ DEFAULT_SYSTEM_USERNAME,
22
+ compute_password_hash,
23
+ )
24
+ from phoenix.config import (
25
+ get_env_admins,
26
+ get_env_default_admin_initial_password,
27
+ )
28
+ from phoenix.db import models
29
+ from phoenix.db.enums import COLUMN_ENUMS, UserRole
30
+ from phoenix.server.email.types import WelcomeEmailSender
31
+ from phoenix.server.types import DbSessionFactory
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ class Facilitator:
37
+ """
38
+ Facilitates the creation of database records necessary for Phoenix to function. This includes
39
+ ensuring that all enum values are present in their respective tables, ensuring that all user
40
+ roles are present, and ensuring that the admin user has a password hash. These tasks will be
41
+ carried out as callbacks at the very beginning of Starlette's lifespan process.
42
+ """
43
+
44
+ def __init__(
45
+ self,
46
+ *,
47
+ db: DbSessionFactory,
48
+ email_sender: Optional[WelcomeEmailSender] = None,
49
+ ) -> None:
50
+ self._db = db
51
+ self._email_sender = email_sender
52
+
53
+ async def __call__(self) -> None:
54
+ for fn in (
55
+ _ensure_enums,
56
+ _ensure_user_roles,
57
+ partial(_ensure_admins, email_sender=self._email_sender),
58
+ ):
59
+ await fn(self._db)
60
+
61
+
62
+ async def _ensure_enums(db: DbSessionFactory) -> None:
63
+ """
64
+ Ensure that all enum values are present in their respective tables. If any values are missing,
65
+ they will be added. If any values are present in the database but not in the enum, an error will
66
+ be raised. This function is idempotent: it will not add duplicate values to the database.
67
+ """
68
+ for column, enum in COLUMN_ENUMS.items():
69
+ table = column.class_
70
+ async with db() as session:
71
+ existing = set(
72
+ [_ async for _ in await session.stream_scalars(select(distinct(column)))]
73
+ )
74
+ expected = set(e.value for e in enum)
75
+ if unexpected := existing - expected:
76
+ raise ValueError(f"Unexpected values in {table.name}.{column.key}: {unexpected}")
77
+ if not (missing := expected - existing):
78
+ continue
79
+ await session.execute(insert(table), [{column.key: v} for v in missing])
80
+
81
+
82
+ async def _ensure_user_roles(db: DbSessionFactory) -> None:
83
+ """
84
+ Ensure that the system and admin roles are present in the database. If they are not, they will
85
+ be added. The system user will have the email "system@localhost" and the admin user will have
86
+ the email "admin@localhost".
87
+ """
88
+ async with db() as session:
89
+ role_ids = {
90
+ name: id_
91
+ async for name, id_ in await session.stream(
92
+ select(models.UserRole.name, models.UserRole.id)
93
+ )
94
+ }
95
+ existing_roles = [
96
+ name
97
+ async for name in await session.stream_scalars(
98
+ select(distinct(models.UserRole.name)).join_from(models.User, models.UserRole)
99
+ )
100
+ ]
101
+ if (system_role := UserRole.SYSTEM.value) not in existing_roles and (
102
+ system_role_id := role_ids.get(system_role)
103
+ ) is not None:
104
+ system_user = models.User(
105
+ user_role_id=system_role_id,
106
+ username=DEFAULT_SYSTEM_USERNAME,
107
+ email=DEFAULT_SYSTEM_EMAIL,
108
+ reset_password=False,
109
+ password_salt=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
110
+ password_hash=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
111
+ )
112
+ session.add(system_user)
113
+ if (admin_role := UserRole.ADMIN.value) not in existing_roles and (
114
+ admin_role_id := role_ids.get(admin_role)
115
+ ) is not None:
116
+ salt = secrets.token_bytes(DEFAULT_SECRET_LENGTH)
117
+ password = get_env_default_admin_initial_password()
118
+ compute = partial(compute_password_hash, password=password, salt=salt)
119
+ loop = asyncio.get_running_loop()
120
+ hash_ = await loop.run_in_executor(None, compute)
121
+ admin_user = models.User(
122
+ user_role_id=admin_role_id,
123
+ username=DEFAULT_ADMIN_USERNAME,
124
+ email=DEFAULT_ADMIN_EMAIL,
125
+ password_salt=salt,
126
+ password_hash=hash_,
127
+ reset_password=True,
128
+ )
129
+ session.add(admin_user)
130
+ await session.flush()
131
+
132
+
133
+ async def _ensure_admins(
134
+ db: DbSessionFactory,
135
+ *,
136
+ email_sender: Optional[WelcomeEmailSender] = None,
137
+ ) -> None:
138
+ """
139
+ Ensure that all startup admin users are present in the database. If any are missing, they will
140
+ be added. Existing records will not be modified.
141
+ """
142
+ if not (admins := get_env_admins()):
143
+ return
144
+ async with db() as session:
145
+ existing_emails = set(
146
+ await session.scalars(
147
+ select(models.User.email).where(models.User.email.in_(admins.keys()))
148
+ )
149
+ )
150
+ admins = {
151
+ email: username for email, username in admins.items() if email not in existing_emails
152
+ }
153
+ if not admins:
154
+ return
155
+ existing_usernames = set(
156
+ await session.scalars(
157
+ select(models.User.username).where(models.User.username.in_(admins.values()))
158
+ )
159
+ )
160
+ admins = {
161
+ email: username
162
+ for email, username in admins.items()
163
+ if username not in existing_usernames
164
+ }
165
+ if not admins:
166
+ return
167
+ admin_role_id = await session.scalar(
168
+ select(models.UserRole.id).filter_by(name=UserRole.ADMIN.value)
169
+ )
170
+ assert admin_role_id is not None, "Admin role not found in database"
171
+ for email, username in admins.items():
172
+ values = dict(
173
+ user_role_id=admin_role_id,
174
+ username=username,
175
+ email=email,
176
+ password_salt=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
177
+ password_hash=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
178
+ reset_password=True,
179
+ )
180
+ await session.execute(insert(models.User).values(values))
181
+ if email_sender is None:
182
+ return
183
+ for exc in await gather(
184
+ *(email_sender.send_welcome_email(email, username) for email, username in admins.items()),
185
+ return_exceptions=True,
186
+ ):
187
+ if isinstance(exc, Exception):
188
+ logger.error(f"Failed to send welcome email: {exc}")
@@ -19,6 +19,7 @@ from sqlalchemy import (
19
19
  )
20
20
  from typing_extensions import assert_never
21
21
 
22
+ from phoenix.config import PLAYGROUND_PROJECT_NAME
22
23
  from phoenix.db import models
23
24
 
24
25
 
@@ -157,3 +158,18 @@ def get_dataset_example_revisions(
157
158
  ),
158
159
  )
159
160
  )
161
+
162
+
163
+ _AnyTuple = TypeVar("_AnyTuple", bound=tuple[Any, ...])
164
+
165
+
166
+ def exclude_experiment_projects(
167
+ stmt: Select[_AnyTuple],
168
+ ) -> Select[_AnyTuple]:
169
+ return stmt.outerjoin(
170
+ models.Experiment,
171
+ and_(
172
+ models.Project.name == models.Experiment.project_name,
173
+ models.Experiment.project_name != PLAYGROUND_PROJECT_NAME,
174
+ ),
175
+ ).where(models.Experiment.project_name.is_(None))
@@ -53,6 +53,7 @@ from phoenix.server.api.dataloaders import (
53
53
  )
54
54
  from phoenix.server.bearer_auth import PhoenixUser
55
55
  from phoenix.server.dml_event import DmlEvent
56
+ from phoenix.server.email.types import EmailSender
56
57
  from phoenix.server.types import (
57
58
  CanGetLastUpdatedAt,
58
59
  CanPutItem,
@@ -124,6 +125,7 @@ class Context(BaseContext):
124
125
  auth_enabled: bool = False
125
126
  secret: Optional[str] = None
126
127
  token_store: Optional[TokenStore] = None
128
+ email_sender: Optional[EmailSender] = None
127
129
 
128
130
  def get_secret(self) -> str:
129
131
  """A type-safe way to get the application secret. Throws an error if the secret is not set.
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import secrets
2
3
  from contextlib import AsyncExitStack
3
4
  from datetime import datetime, timezone
@@ -32,6 +33,8 @@ from phoenix.server.api.types.User import User, to_gql_user
32
33
  from phoenix.server.bearer_auth import PhoenixUser
33
34
  from phoenix.server.types import AccessTokenId, ApiKeyId, PasswordResetTokenId, RefreshTokenId
34
35
 
36
+ logger = logging.getLogger(__name__)
37
+
35
38
 
36
39
  @strawberry.input
37
40
  class CreateUserInput:
@@ -39,6 +42,7 @@ class CreateUserInput:
39
42
  username: str
40
43
  password: str
41
44
  role: UserRoleInput
45
+ send_welcome_email: Optional[bool] = False
42
46
 
43
47
 
44
48
  @strawberry.input
@@ -111,6 +115,12 @@ class UserMutationMixin:
111
115
  await session.flush()
112
116
  except (PostgreSQLIntegrityError, SQLiteIntegrityError) as error:
113
117
  raise Conflict(_user_operation_error_message(error))
118
+ if input.send_welcome_email and info.context.email_sender is not None:
119
+ try:
120
+ await info.context.email_sender.send_welcome_email(user.email, user.username)
121
+ except Exception as error:
122
+ # Log the error but do not raise it
123
+ logger.error(f"Failed to send welcome email: {error}")
114
124
  return UserMutationPayload(user=to_gql_user(user))
115
125
 
116
126
  @strawberry.mutation(permission_classes=[IsNotReadOnly, IsAdmin, IsLocked]) # type: ignore
@@ -19,7 +19,7 @@ from phoenix.config import (
19
19
  getenv,
20
20
  )
21
21
  from phoenix.db import enums, models
22
- from phoenix.db.helpers import SupportedSQLDialect
22
+ from phoenix.db.helpers import SupportedSQLDialect, exclude_experiment_projects
23
23
  from phoenix.db.models import DatasetExample as OrmExample
24
24
  from phoenix.db.models import DatasetExampleRevision as OrmRevision
25
25
  from phoenix.db.models import DatasetVersion as OrmVersion
@@ -42,7 +42,6 @@ from phoenix.server.api.input_types.ClusterInput import ClusterInput
42
42
  from phoenix.server.api.input_types.Coordinates import InputCoordinate2D, InputCoordinate3D
43
43
  from phoenix.server.api.input_types.DatasetSort import DatasetSort
44
44
  from phoenix.server.api.input_types.InvocationParameters import InvocationParameter
45
- from phoenix.server.api.subscriptions import PLAYGROUND_PROJECT_NAME
46
45
  from phoenix.server.api.types.Cluster import Cluster, to_gql_clusters
47
46
  from phoenix.server.api.types.Dataset import Dataset, to_gql_dataset
48
47
  from phoenix.server.api.types.DatasetExample import DatasetExample
@@ -233,18 +232,8 @@ class Query:
233
232
  last=last,
234
233
  before=before if isinstance(before, CursorString) else None,
235
234
  )
236
- stmt = (
237
- select(models.Project)
238
- .outerjoin(
239
- models.Experiment,
240
- and_(
241
- models.Project.name == models.Experiment.project_name,
242
- models.Experiment.project_name != PLAYGROUND_PROJECT_NAME,
243
- ),
244
- )
245
- .where(models.Experiment.project_name.is_(None))
246
- .order_by(models.Project.id)
247
- )
235
+ stmt = select(models.Project).order_by(models.Project.id)
236
+ stmt = exclude_experiment_projects(stmt)
248
237
  async with info.context.db() as session:
249
238
  projects = await session.stream_scalars(stmt)
250
239
  data = [
@@ -9,6 +9,7 @@ from .evaluations import router as evaluations_router
9
9
  from .experiment_evaluations import router as experiment_evaluations_router
10
10
  from .experiment_runs import router as experiment_runs_router
11
11
  from .experiments import router as experiments_router
12
+ from .projects import router as projects_router
12
13
  from .prompts import router as prompts_router
13
14
  from .spans import router as spans_router
14
15
  from .traces import router as traces_router
@@ -63,4 +64,5 @@ def create_v1_router(authentication_enabled: bool) -> APIRouter:
63
64
  router.include_router(spans_router)
64
65
  router.include_router(evaluations_router)
65
66
  router.include_router(prompts_router)
67
+ router.include_router(projects_router)
66
68
  return router