arize-phoenix 10.15.0__tar.gz → 11.0.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 (446) hide show
  1. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/.gitignore +3 -1
  2. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/PKG-INFO +2 -2
  3. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/pyproject.toml +1 -1
  4. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/config.py +5 -2
  5. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/datetime_utils.py +8 -1
  6. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/bulk_inserter.py +40 -1
  7. arize_phoenix-11.0.0/src/phoenix/db/facilitator.py +522 -0
  8. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/helpers.py +15 -0
  9. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/span.py +3 -1
  10. arize_phoenix-11.0.0/src/phoenix/db/migrations/versions/a20694b15f82_cost.py +196 -0
  11. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/models.py +267 -9
  12. arize_phoenix-11.0.0/src/phoenix/db/types/token_price_customization.py +29 -0
  13. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/context.py +38 -4
  14. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/__init__.py +41 -5
  15. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/last_used_times_by_generative_model_id.py +35 -0
  16. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_by_span.py +24 -0
  17. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_generative_model.py +56 -0
  18. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_project_session.py +57 -0
  19. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_span.py +43 -0
  20. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_detail_summary_entries_by_trace.py +56 -0
  21. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_details_by_span_cost.py +27 -0
  22. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_summary_by_experiment.py +58 -0
  23. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_summary_by_experiment_run.py +58 -0
  24. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_summary_by_generative_model.py +55 -0
  25. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_summary_by_project.py +140 -0
  26. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_summary_by_project_session.py +56 -0
  27. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_cost_summary_by_trace.py +55 -0
  28. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/span_costs.py +35 -0
  29. arize_phoenix-11.0.0/src/phoenix/server/api/dataloaders/types.py +29 -0
  30. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/playground_clients.py +103 -12
  31. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ProjectSessionSort.py +3 -0
  32. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/SpanSort.py +17 -0
  33. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/__init__.py +2 -0
  34. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/chat_mutations.py +17 -0
  35. arize_phoenix-11.0.0/src/phoenix/server/api/mutations/model_mutations.py +208 -0
  36. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/queries.py +82 -41
  37. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/traces.py +11 -4
  38. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/subscriptions.py +36 -2
  39. arize_phoenix-11.0.0/src/phoenix/server/api/types/CostBreakdown.py +15 -0
  40. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Experiment.py +59 -1
  41. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ExperimentRun.py +58 -4
  42. arize_phoenix-11.0.0/src/phoenix/server/api/types/GenerativeModel.py +150 -0
  43. arize_phoenix-10.15.0/src/phoenix/server/api/types/Model.py → arize_phoenix-11.0.0/src/phoenix/server/api/types/InferenceModel.py +1 -1
  44. arize_phoenix-11.0.0/src/phoenix/server/api/types/ModelInterface.py +11 -0
  45. arize_phoenix-11.0.0/src/phoenix/server/api/types/PlaygroundModel.py +10 -0
  46. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Project.py +42 -0
  47. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ProjectSession.py +44 -0
  48. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Span.py +137 -0
  49. arize_phoenix-11.0.0/src/phoenix/server/api/types/SpanCostDetailSummaryEntry.py +10 -0
  50. arize_phoenix-11.0.0/src/phoenix/server/api/types/SpanCostSummary.py +10 -0
  51. arize_phoenix-11.0.0/src/phoenix/server/api/types/TokenPrice.py +16 -0
  52. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/TokenUsage.py +3 -3
  53. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Trace.py +41 -0
  54. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/app.py +59 -0
  55. arize_phoenix-11.0.0/src/phoenix/server/cost_tracking/cost_details_calculator.py +190 -0
  56. arize_phoenix-11.0.0/src/phoenix/server/cost_tracking/cost_model_lookup.py +151 -0
  57. arize_phoenix-11.0.0/src/phoenix/server/cost_tracking/helpers.py +68 -0
  58. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/cost_tracking/model_cost_manifest.json +59 -329
  59. arize_phoenix-11.0.0/src/phoenix/server/cost_tracking/regex_specificity.py +397 -0
  60. arize_phoenix-11.0.0/src/phoenix/server/cost_tracking/token_cost_calculator.py +57 -0
  61. arize_phoenix-11.0.0/src/phoenix/server/daemons/generative_model_store.py +51 -0
  62. arize_phoenix-11.0.0/src/phoenix/server/daemons/span_cost_calculator.py +103 -0
  63. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/dml_event_handler.py +1 -0
  64. arize_phoenix-11.0.0/src/phoenix/server/static/.vite/manifest.json +87 -0
  65. arize_phoenix-11.0.0/src/phoenix/server/static/assets/components-BnK9kodr.js +5055 -0
  66. arize_phoenix-10.15.0/src/phoenix/server/static/assets/index-DIlhmbjB.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/index-S3YKLmbo.js +13 -13
  67. arize_phoenix-10.15.0/src/phoenix/server/static/assets/pages-YX47cEoQ.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/pages-BW6PBHZb.js +811 -419
  68. arize_phoenix-10.15.0/src/phoenix/server/static/assets/vendor-DCZoBorz.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/vendor-DqQvHbPa.js +147 -147
  69. arize_phoenix-10.15.0/src/phoenix/server/static/assets/vendor-arizeai-Ckci3irT.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/vendor-arizeai-CLX44PFA.js +1 -1
  70. arize_phoenix-10.15.0/src/phoenix/server/static/assets/vendor-codemirror-BODM513D.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/vendor-codemirror-Du3XyJnB.js +1 -1
  71. arize_phoenix-10.15.0/src/phoenix/server/static/assets/vendor-recharts-C9O2a-N3.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/vendor-recharts-B2PJDrnX.js +25 -25
  72. arize_phoenix-10.15.0/src/phoenix/server/static/assets/vendor-shiki-Dq54rRC7.js → arize_phoenix-11.0.0/src/phoenix/server/static/assets/vendor-shiki-CNbrFjf9.js +1 -1
  73. arize_phoenix-11.0.0/src/phoenix/utilities/span_store.py +0 -0
  74. arize_phoenix-11.0.0/src/phoenix/version.py +1 -0
  75. arize_phoenix-10.15.0/src/phoenix/db/facilitator.py +0 -263
  76. arize_phoenix-10.15.0/src/phoenix/server/api/types/GenerativeModel.py +0 -9
  77. arize_phoenix-10.15.0/src/phoenix/server/cost_tracking/cost_lookup.py +0 -255
  78. arize_phoenix-10.15.0/src/phoenix/server/static/.vite/manifest.json +0 -87
  79. arize_phoenix-10.15.0/src/phoenix/server/static/assets/components-SpUMF1qV.js +0 -4509
  80. arize_phoenix-10.15.0/src/phoenix/version.py +0 -1
  81. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/IP_NOTICE +0 -0
  82. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/LICENSE +0 -0
  83. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/README.md +0 -0
  84. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/__init__.py +0 -0
  85. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/auth.py +0 -0
  86. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/core/__init__.py +0 -0
  87. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/core/embedding_dimension.py +0 -0
  88. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/core/model.py +0 -0
  89. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/core/model_schema.py +0 -0
  90. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  91. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/README.md +0 -0
  92. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/__init__.py +0 -0
  93. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/alembic.ini +0 -0
  94. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/constants.py +0 -0
  95. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/engines.py +0 -0
  96. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/enums.py +0 -0
  97. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/helpers.py +0 -0
  98. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/__init__.py +0 -0
  99. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/constants.py +0 -0
  100. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/dataset.py +0 -0
  101. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/document_annotation.py +0 -0
  102. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/evaluation.py +0 -0
  103. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/span_annotation.py +0 -0
  104. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/trace_annotation.py +0 -0
  105. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/insertion/types.py +0 -0
  106. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrate.py +0 -0
  107. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/__init__.py +0 -0
  108. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/data_migration_scripts/__init__.py +0 -0
  109. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/data_migration_scripts/populate_project_sessions.py +0 -0
  110. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/env.py +0 -0
  111. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/script.py.mako +0 -0
  112. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  113. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/2f9d1a65945f_annotation_config_migration.py +0 -0
  114. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +0 -0
  115. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/4ded9e43755f_create_project_sessions_table.py +0 -0
  116. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/6a88424799fe_update_users_with_auth_method.py +0 -0
  117. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/8a3764fe7f1a_change_jsonb_to_json_for_prompts.py +0 -0
  118. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/bb8139330879_create_project_trace_retention_policies_table.py +0 -0
  119. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/bc8fea3c2bc8_add_prompt_tables.py +0 -0
  120. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/cd164e83824f_users_and_tokens.py +0 -0
  121. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  122. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/pg_config.py +0 -0
  123. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/types/__init__.py +0 -0
  124. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/types/annotation_configs.py +0 -0
  125. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/types/db_models.py +0 -0
  126. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/types/identifier.py +0 -0
  127. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/types/model_provider.py +0 -0
  128. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/db/types/trace_retention.py +0 -0
  129. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/exceptions.py +0 -0
  130. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/__init__.py +0 -0
  131. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  132. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/evaluators/base.py +0 -0
  133. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  134. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  135. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
  136. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/functions.py +0 -0
  137. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/tracing.py +0 -0
  138. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/types.py +0 -0
  139. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/experiments/utils.py +0 -0
  140. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/inferences/__init__.py +0 -0
  141. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/inferences/errors.py +0 -0
  142. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/inferences/fixtures.py +0 -0
  143. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/inferences/inferences.py +0 -0
  144. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/inferences/schema.py +0 -0
  145. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/inferences/validation.py +0 -0
  146. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/logging/__init__.py +0 -0
  147. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/logging/_config.py +0 -0
  148. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/logging/_filter.py +0 -0
  149. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/logging/_formatter.py +0 -0
  150. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/README.md +0 -0
  151. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/__init__.py +0 -0
  152. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/binning.py +0 -0
  153. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/metrics.py +0 -0
  154. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/mixins.py +0 -0
  155. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  156. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/timeseries.py +0 -0
  157. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/metrics/wrappers.py +0 -0
  158. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/pointcloud/__init__.py +0 -0
  159. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/pointcloud/clustering.py +0 -0
  160. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  161. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/pointcloud/projectors.py +0 -0
  162. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  163. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/py.typed +0 -0
  164. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/__init__.py +0 -0
  165. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/README.md +0 -0
  166. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/__init__.py +0 -0
  167. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/auth.py +0 -0
  168. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  169. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  170. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  171. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  172. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  173. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  174. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  175. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  176. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  177. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  178. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  179. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/experiment_run_annotations.py +0 -0
  180. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  181. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  182. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  183. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  184. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/num_child_spans.py +0 -0
  185. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/num_spans_per_trace.py +0 -0
  186. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  187. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/project_ids_by_trace_retention_policy_id.py +0 -0
  188. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/prompt_version_sequence_number.py +0 -0
  189. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  190. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/session_io.py +0 -0
  191. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/session_num_traces.py +0 -0
  192. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/session_num_traces_with_error.py +0 -0
  193. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/session_token_usages.py +0 -0
  194. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/session_trace_latency_ms_quantile.py +0 -0
  195. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  196. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/span_by_id.py +0 -0
  197. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  198. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  199. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  200. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/table_fields.py +0 -0
  201. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  202. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/trace_by_trace_ids.py +0 -0
  203. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/trace_retention_policy_id_by_project_id.py +0 -0
  204. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/trace_root_spans.py +0 -0
  205. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/user_roles.py +0 -0
  206. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/dataloaders/users.py +0 -0
  207. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/exceptions.py +0 -0
  208. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
  209. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/annotations.py +0 -0
  210. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  211. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/experiment_run_filters.py +0 -0
  212. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/playground_registry.py +0 -0
  213. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/playground_spans.py +0 -0
  214. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/prompts/__init__.py +0 -0
  215. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/prompts/conversions/__init__.py +0 -0
  216. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/prompts/conversions/anthropic.py +0 -0
  217. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/prompts/conversions/aws.py +0 -0
  218. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/prompts/conversions/openai.py +0 -0
  219. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/helpers/prompts/models.py +0 -0
  220. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  221. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  222. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ChatCompletionInput.py +0 -0
  223. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ChatCompletionMessageInput.py +0 -0
  224. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  225. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  226. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  227. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  228. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  229. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  230. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  231. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  232. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DatasetFilter.py +0 -0
  233. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  234. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  235. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  236. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  237. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  238. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  239. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  240. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  241. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/GenerativeCredentialInput.py +0 -0
  242. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/GenerativeModelInput.py +0 -0
  243. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  244. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/InvocationParameters.py +0 -0
  245. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  246. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  247. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  248. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  249. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ProjectFilter.py +0 -0
  250. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/ProjectSort.py +0 -0
  251. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/PromptTemplateOptions.py +0 -0
  252. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/PromptVersionInput.py +0 -0
  253. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/SpanAnnotationFilter.py +0 -0
  254. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  255. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  256. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  257. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/UserRoleInput.py +0 -0
  258. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
  259. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/interceptor.py +0 -0
  260. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/annotation_config_mutations.py +0 -0
  261. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/api_key_mutations.py +0 -0
  262. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
  263. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
  264. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  265. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
  266. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +0 -0
  267. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/prompt_label_mutations.py +0 -0
  268. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/prompt_mutations.py +0 -0
  269. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/prompt_version_tag_mutations.py +0 -0
  270. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +0 -0
  271. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +0 -0
  272. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/trace_mutations.py +0 -0
  273. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/mutations/user_mutations.py +0 -0
  274. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/openapi/__init__.py +0 -0
  275. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/openapi/main.py +0 -0
  276. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/openapi/schema.py +0 -0
  277. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/__init__.py +0 -0
  278. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/auth.py +0 -0
  279. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/embeddings.py +0 -0
  280. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/oauth2.py +0 -0
  281. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/utils.py +0 -0
  282. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/__init__.py +0 -0
  283. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/annotation_configs.py +0 -0
  284. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/annotations.py +0 -0
  285. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/datasets.py +0 -0
  286. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  287. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -0
  288. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -0
  289. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/experiments.py +0 -0
  290. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/models.py +0 -0
  291. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/projects.py +0 -0
  292. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/prompts.py +0 -0
  293. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/spans.py +0 -0
  294. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/users.py +0 -0
  295. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  296. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/schema.py +0 -0
  297. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Annotation.py +0 -0
  298. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/AnnotationConfig.py +0 -0
  299. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/AnnotationSource.py +0 -0
  300. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  301. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  302. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ApiKey.py +0 -0
  303. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/AuthMethod.py +0 -0
  304. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ChatCompletionMessageRole.py +0 -0
  305. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +0 -0
  306. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  307. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  308. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/CronExpression.py +0 -0
  309. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  310. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  311. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  312. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  313. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  314. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  315. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  316. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  317. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  318. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  319. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  320. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  321. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  322. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  323. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  324. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
  325. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  326. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Event.py +0 -0
  327. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  328. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  329. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  330. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  331. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  332. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  333. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  334. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/GenerativeProvider.py +0 -0
  335. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Identifier.py +0 -0
  336. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Inferences.py +0 -0
  337. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  338. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  339. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  340. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  341. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  342. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ProjectTraceRetentionPolicy.py +0 -0
  343. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Prompt.py +0 -0
  344. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/PromptLabel.py +0 -0
  345. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  346. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/PromptVersion.py +0 -0
  347. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/PromptVersionTag.py +0 -0
  348. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/PromptVersionTemplate.py +0 -0
  349. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ResponseFormat.py +0 -0
  350. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  351. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  352. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/Segments.py +0 -0
  353. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  354. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  355. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/SpanIOValue.py +0 -0
  356. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/SystemApiKey.py +0 -0
  357. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  358. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/TokenCountPromptDetails.py +0 -0
  359. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ToolDefinition.py +0 -0
  360. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  361. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  362. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/User.py +0 -0
  363. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/UserApiKey.py +0 -0
  364. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/UserRole.py +0 -0
  365. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  366. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  367. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/__init__.py +0 -0
  368. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/node.py +0 -0
  369. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/types/pagination.py +0 -0
  370. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/api/utils.py +0 -0
  371. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/authorization.py +0 -0
  372. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/bearer_auth.py +0 -0
  373. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/cost_tracking/__init__.py +0 -0
  374. {arize_phoenix-10.15.0/src/phoenix/server/email → arize_phoenix-11.0.0/src/phoenix/server/daemons}/__init__.py +0 -0
  375. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/dml_event.py +0 -0
  376. {arize_phoenix-10.15.0/src/phoenix/server/email/templates → arize_phoenix-11.0.0/src/phoenix/server/email}/__init__.py +0 -0
  377. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/email/sender.py +0 -0
  378. {arize_phoenix-10.15.0/src/phoenix/server/middleware → arize_phoenix-11.0.0/src/phoenix/server/email/templates}/__init__.py +0 -0
  379. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/email/templates/password_reset.html +0 -0
  380. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/email/templates/welcome.html +0 -0
  381. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/email/types.py +0 -0
  382. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/grpc_server.py +0 -0
  383. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/jwt_store.py +0 -0
  384. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/main.py +0 -0
  385. {arize_phoenix-10.15.0/src/phoenix/server/openapi → arize_phoenix-11.0.0/src/phoenix/server/middleware}/__init__.py +0 -0
  386. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/middleware/gzip.py +0 -0
  387. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/oauth2.py +0 -0
  388. {arize_phoenix-10.15.0/src/phoenix/server/templates → arize_phoenix-11.0.0/src/phoenix/server/openapi}/__init__.py +0 -0
  389. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/prometheus.py +0 -0
  390. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/rate_limiters.py +0 -0
  391. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/retention.py +0 -0
  392. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  393. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  394. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  395. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  396. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  397. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  398. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  399. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  400. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/assets/vendor-WIZid84E.css +0 -0
  401. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/assets/vendor-three-C5WAXd5r.js +0 -0
  402. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/favicon.ico +0 -0
  403. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/static/modernizr.js +0 -0
  404. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/telemetry.py +0 -0
  405. {arize_phoenix-10.15.0/src/phoenix/session → arize_phoenix-11.0.0/src/phoenix/server/templates}/__init__.py +0 -0
  406. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/templates/index.html +0 -0
  407. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/thread_server.py +0 -0
  408. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/server/types.py +0 -0
  409. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/services.py +0 -0
  410. /arize_phoenix-10.15.0/src/phoenix/utilities/span_store.py → /arize_phoenix-11.0.0/src/phoenix/session/__init__.py +0 -0
  411. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/session/client.py +0 -0
  412. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/session/data_extractor.py +0 -0
  413. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/session/evaluation.py +0 -0
  414. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/session/session.py +0 -0
  415. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/settings.py +0 -0
  416. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/__init__.py +0 -0
  417. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/attributes.py +0 -0
  418. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/dsl/README.md +0 -0
  419. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  420. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/dsl/filter.py +0 -0
  421. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  422. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/dsl/query.py +0 -0
  423. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/errors.py +0 -0
  424. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  425. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/exporter.py +0 -0
  426. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/fixtures.py +0 -0
  427. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/otel.py +0 -0
  428. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/projects.py +0 -0
  429. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/schemas.py +0 -0
  430. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/span_evaluations.py +0 -0
  431. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  432. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  433. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/trace_dataset.py +0 -0
  434. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/utils.py +0 -0
  435. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/v1/__init__.py +0 -0
  436. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  437. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  438. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/__init__.py +0 -0
  439. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/client.py +0 -0
  440. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/deprecation.py +0 -0
  441. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/error_handling.py +0 -0
  442. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/json.py +0 -0
  443. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/logging.py +0 -0
  444. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/project.py +0 -0
  445. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/re.py +0 -0
  446. {arize_phoenix-10.15.0 → arize_phoenix-11.0.0}/src/phoenix/utilities/template_formatters.py +0 -0
@@ -85,4 +85,6 @@ packages/phoenix-client/docs/build/
85
85
  packages/phoenix-evals/docs/build/
86
86
 
87
87
  # Deployment
88
- helm/charts/*.tgz
88
+ helm/charts/*.tgz
89
+ # mypy
90
+ .mypy_cache
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arize-phoenix
3
- Version: 10.15.0
3
+ Version: 11.0.0
4
4
  Summary: AI Observability and Evaluation
5
5
  Project-URL: Documentation, https://arize.com/docs/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -33,7 +33,7 @@ Requires-Dist: httpx
33
33
  Requires-Dist: jinja2
34
34
  Requires-Dist: numpy!=2.0.0
35
35
  Requires-Dist: openinference-instrumentation>=0.1.32
36
- Requires-Dist: openinference-semantic-conventions>=0.1.17
36
+ Requires-Dist: openinference-semantic-conventions>=0.1.20
37
37
  Requires-Dist: opentelemetry-exporter-otlp
38
38
  Requires-Dist: opentelemetry-proto>=1.12.0
39
39
  Requires-Dist: opentelemetry-sdk
@@ -43,7 +43,7 @@ dependencies = [
43
43
  "opentelemetry-proto>=1.12.0", # needed to avoid this issue: https://github.com/Arize-ai/phoenix/issues/2695
44
44
  "opentelemetry-exporter-otlp",
45
45
  "opentelemetry-semantic-conventions",
46
- "openinference-semantic-conventions>=0.1.17",
46
+ "openinference-semantic-conventions>=0.1.20",
47
47
  "openinference-instrumentation>=0.1.32",
48
48
  "sqlalchemy[asyncio]>=2.0.4, <3",
49
49
  "alembic>=1.3.0, <2",
@@ -135,8 +135,11 @@ ENV_PHOENIX_DANGEROUSLY_DISABLE_MIGRATIONS = "PHOENIX_DANGEROUSLY_DISABLE_MIGRAT
135
135
  """
136
136
  Whether or not to disable migrations. Defaults to None / False.
137
137
 
138
- This should only be used by developers working on the Phoenix server that need to be
139
- switching between branches without having to run migrations.
138
+ This should only be used by developers working on the Phoenix server that need
139
+ to be switching between branches without having to run migrations.
140
+
141
+ This can also be useful if a migration fails and you want to put the applicaiton
142
+ in a running state.
140
143
  """
141
144
 
142
145
  # Phoenix server OpenTelemetry instrumentation environment variables
@@ -28,7 +28,7 @@ def normalize_datetime(
28
28
  """
29
29
  if not isinstance(dt, datetime):
30
30
  return None
31
- if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None:
31
+ if not is_timezone_aware(dt):
32
32
  dt = dt.replace(tzinfo=tz if tz else _LOCAL_TIMEZONE)
33
33
  return dt.astimezone(timezone.utc)
34
34
 
@@ -106,3 +106,10 @@ def right_open_time_range(
106
106
  floor_to_minute(min_time) if min_time else None,
107
107
  floor_to_minute(max_time + timedelta(minutes=1)) if max_time else None,
108
108
  )
109
+
110
+
111
+ def is_timezone_aware(dt: datetime) -> bool:
112
+ """
113
+ Returns True if the datetime is timezone-aware, False otherwise.
114
+ """
115
+ return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None
@@ -8,6 +8,7 @@ from itertools import islice
8
8
  from time import perf_counter
9
9
  from typing import Any, Optional, cast
10
10
 
11
+ from openinference.semconv.trace import SpanAttributes
11
12
  from typing_extensions import TypeAlias
12
13
 
13
14
  import phoenix.trace.v1 as pb
@@ -17,11 +18,19 @@ from phoenix.db.insertion.evaluation import (
17
18
  InsertEvaluationError,
18
19
  insert_evaluation,
19
20
  )
20
- from phoenix.db.insertion.helpers import DataManipulation, DataManipulationEvent
21
+ from phoenix.db.insertion.helpers import (
22
+ DataManipulation,
23
+ DataManipulationEvent,
24
+ should_calculate_span_cost,
25
+ )
21
26
  from phoenix.db.insertion.span import SpanInsertionEvent, insert_span
22
27
  from phoenix.db.insertion.span_annotation import SpanAnnotationQueueInserter
23
28
  from phoenix.db.insertion.trace_annotation import TraceAnnotationQueueInserter
24
29
  from phoenix.db.insertion.types import Insertables, Precursors
30
+ from phoenix.server.daemons.span_cost_calculator import (
31
+ SpanCostCalculator,
32
+ SpanCostCalculatorQueueItem,
33
+ )
25
34
  from phoenix.server.dml_event import DmlEvent, SpanInsertEvent
26
35
  from phoenix.server.types import CanPutItem, DbSessionFactory
27
36
  from phoenix.trace.schemas import Span
@@ -42,6 +51,7 @@ class BulkInserter:
42
51
  db: DbSessionFactory,
43
52
  *,
44
53
  event_queue: CanPutItem[DmlEvent],
54
+ span_cost_calculator: SpanCostCalculator,
45
55
  initial_batch_of_spans: Optional[Iterable[tuple[Span, str]]] = None,
46
56
  initial_batch_of_evaluations: Optional[Iterable[pb.Evaluation]] = None,
47
57
  sleep: float = 0.1,
@@ -78,6 +88,7 @@ class BulkInserter:
78
88
  self._retry_delay_sec = retry_delay_sec
79
89
  self._retry_allowance = retry_allowance
80
90
  self._queue_inserters = _QueueInserters(db, self._retry_delay_sec, self._retry_allowance)
91
+ self._span_cost_calculator = span_cost_calculator
81
92
 
82
93
  async def __aenter__(
83
94
  self,
@@ -175,6 +186,7 @@ class BulkInserter:
175
186
 
176
187
  async def _insert_spans(self, spans: list[tuple[Span, str]]) -> None:
177
188
  project_ids = set()
189
+ span_cost_calculator_queue: list[SpanCostCalculatorQueueItem] = []
178
190
  for i in range(0, len(spans), self._max_ops_per_transaction):
179
191
  try:
180
192
  start = perf_counter()
@@ -198,6 +210,16 @@ class BulkInserter:
198
210
  )
199
211
  if result is not None:
200
212
  project_ids.add(result.project_rowid)
213
+ if should_calculate_span_cost(span.attributes):
214
+ span_cost_calculator_queue.append(
215
+ SpanCostCalculatorQueueItem(
216
+ span_rowid=result.span_rowid,
217
+ trace_rowid=result.trace_rowid,
218
+ attributes=span.attributes,
219
+ span_start_time=span.start_time,
220
+ )
221
+ )
222
+
201
223
  if self._enable_prometheus:
202
224
  from phoenix.server.prometheus import BULK_LOADER_INSERTION_TIME
203
225
 
@@ -209,6 +231,8 @@ class BulkInserter:
209
231
  BULK_LOADER_EXCEPTIONS.inc()
210
232
  logger.exception("Failed to insert spans")
211
233
  self._event_queue.put(SpanInsertEvent(tuple(project_ids)))
234
+ for item in span_cost_calculator_queue:
235
+ self._span_cost_calculator.put_nowait(item)
212
236
 
213
237
  async def _insert_evaluations(self, evaluations: list[pb.Evaluation]) -> None:
214
238
  for i in range(0, len(evaluations), self._max_ops_per_transaction):
@@ -292,3 +316,18 @@ class _QueueInserters:
292
316
  @_enqueue.register(Insertables.DocumentAnnotation)
293
317
  async def _(self, item: Precursors.DocumentAnnotation) -> None:
294
318
  await self._document_annotations.enqueue(item)
319
+
320
+
321
+ LLM_MODEL_NAME = SpanAttributes.LLM_MODEL_NAME
322
+ LLM_PROVIDER = SpanAttributes.LLM_PROVIDER
323
+ LLM_TOKEN_COUNT_COMPLETION = SpanAttributes.LLM_TOKEN_COUNT_COMPLETION
324
+ LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO = SpanAttributes.LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO
325
+ LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING = (
326
+ SpanAttributes.LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING
327
+ )
328
+ LLM_TOKEN_COUNT_PROMPT = SpanAttributes.LLM_TOKEN_COUNT_PROMPT
329
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO = SpanAttributes.LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO
330
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ = SpanAttributes.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ
331
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE = (
332
+ SpanAttributes.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE
333
+ )
@@ -0,0 +1,522 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import json
5
+ import logging
6
+ import re
7
+ import secrets
8
+ from asyncio import gather
9
+ from datetime import datetime, timedelta, timezone
10
+ from functools import partial
11
+ from pathlib import Path
12
+ from typing import NamedTuple, Optional, Union
13
+
14
+ import sqlalchemy as sa
15
+ from sqlalchemy import select
16
+ from sqlalchemy.orm import InstrumentedAttribute, joinedload
17
+ from sqlalchemy.sql.dml import ReturningDelete
18
+
19
+ from phoenix import config
20
+ from phoenix.auth import (
21
+ DEFAULT_ADMIN_EMAIL,
22
+ DEFAULT_ADMIN_USERNAME,
23
+ DEFAULT_SECRET_LENGTH,
24
+ DEFAULT_SYSTEM_EMAIL,
25
+ DEFAULT_SYSTEM_USERNAME,
26
+ compute_password_hash,
27
+ )
28
+ from phoenix.config import (
29
+ get_env_admins,
30
+ get_env_default_admin_initial_password,
31
+ get_env_disable_basic_auth,
32
+ )
33
+ from phoenix.db import models
34
+ from phoenix.db.constants import DEFAULT_PROJECT_TRACE_RETENTION_POLICY_ID
35
+ from phoenix.db.enums import ENUM_COLUMNS
36
+ from phoenix.db.types.trace_retention import (
37
+ MaxDaysRule,
38
+ TraceRetentionCronExpression,
39
+ TraceRetentionRule,
40
+ )
41
+ from phoenix.server.email.types import WelcomeEmailSender
42
+ from phoenix.server.types import DbSessionFactory
43
+
44
+ logger = logging.getLogger(__name__)
45
+
46
+
47
+ class Facilitator:
48
+ """
49
+ Facilitates the creation of database records necessary for Phoenix to function. This includes
50
+ ensuring that all enum values are present in their respective tables, ensuring that all user
51
+ roles are present, and ensuring that the admin user has a password hash. These tasks will be
52
+ carried out as callbacks at the very beginning of Starlette's lifespan process.
53
+ """
54
+
55
+ def __init__(
56
+ self,
57
+ *,
58
+ db: DbSessionFactory,
59
+ email_sender: Optional[WelcomeEmailSender] = None,
60
+ ) -> None:
61
+ self._db = db
62
+ self._email_sender = email_sender
63
+
64
+ async def __call__(self) -> None:
65
+ for fn in (
66
+ _ensure_enums,
67
+ _ensure_user_roles,
68
+ _get_system_user_id,
69
+ partial(_ensure_admins, email_sender=self._email_sender),
70
+ _ensure_default_project_trace_retention_policy,
71
+ _ensure_model_costs,
72
+ _delete_expired_childless_records,
73
+ ):
74
+ await fn(self._db)
75
+
76
+
77
+ async def _ensure_enums(db: DbSessionFactory) -> None:
78
+ """
79
+ Ensure that all enum values are present in their respective tables. If any values are missing,
80
+ they will be added. If any values are present in the database but not in the enum, an error will
81
+ be raised. This function is idempotent: it will not add duplicate values to the database.
82
+ """
83
+ for column in ENUM_COLUMNS:
84
+ table = column.class_
85
+ assert isinstance(column.type, sa.Enum)
86
+ async with db() as session:
87
+ existing = set(await session.scalars(sa.select(column)))
88
+ expected = set(column.type.enums)
89
+ if unexpected := existing - expected:
90
+ raise ValueError(f"Unexpected values in {table.name}.{column.key}: {unexpected}")
91
+ if not (missing := expected - existing):
92
+ continue
93
+ await session.execute(sa.insert(table), [{column.key: v} for v in missing])
94
+
95
+
96
+ async def _ensure_user_roles(db: DbSessionFactory) -> None:
97
+ """
98
+ Ensure that the system and admin roles are present in the database. If they are not, they will
99
+ be added. The system user will have the email "system@localhost" and the admin user will have
100
+ the email "admin@localhost".
101
+ """
102
+ async with db() as session:
103
+ role_ids: dict[models.UserRoleName, int] = {
104
+ name: id_
105
+ async for name, id_ in await session.stream(
106
+ sa.select(models.UserRole.name, models.UserRole.id)
107
+ )
108
+ }
109
+ existing_roles: list[models.UserRoleName] = [
110
+ name
111
+ async for name in await session.stream_scalars(
112
+ sa.select(sa.distinct(models.UserRole.name)).join_from(models.User, models.UserRole)
113
+ )
114
+ ]
115
+ if (
116
+ "SYSTEM" not in existing_roles
117
+ and (system_role_id := role_ids.get("SYSTEM")) is not None
118
+ ):
119
+ system_user = models.LocalUser(
120
+ user_role_id=system_role_id,
121
+ username=DEFAULT_SYSTEM_USERNAME,
122
+ email=DEFAULT_SYSTEM_EMAIL,
123
+ reset_password=False,
124
+ password_salt=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
125
+ password_hash=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
126
+ )
127
+ session.add(system_user)
128
+ if "ADMIN" not in existing_roles and (admin_role_id := role_ids.get("ADMIN")) is not None:
129
+ salt = secrets.token_bytes(DEFAULT_SECRET_LENGTH)
130
+ password = get_env_default_admin_initial_password()
131
+ compute = partial(compute_password_hash, password=password, salt=salt)
132
+ loop = asyncio.get_running_loop()
133
+ hash_ = await loop.run_in_executor(None, compute)
134
+ admin_user = models.LocalUser(
135
+ user_role_id=admin_role_id,
136
+ username=DEFAULT_ADMIN_USERNAME,
137
+ email=DEFAULT_ADMIN_EMAIL,
138
+ password_salt=salt,
139
+ password_hash=hash_,
140
+ reset_password=True,
141
+ )
142
+ session.add(admin_user)
143
+ await session.flush()
144
+
145
+
146
+ async def _get_system_user_id(db: DbSessionFactory) -> None:
147
+ """
148
+ Set the system user ID in the config. This is used to identify the system user in the database.
149
+ """
150
+ async with db() as session:
151
+ system_user_id = await session.scalar(
152
+ sa.select(models.User.id)
153
+ .join(models.UserRole)
154
+ .where(models.UserRole.name == "SYSTEM")
155
+ .order_by(models.User.id)
156
+ .limit(1)
157
+ )
158
+ if system_user_id is None:
159
+ raise ValueError("System user not found in database")
160
+ config.SYSTEM_USER_ID = system_user_id
161
+
162
+
163
+ async def _ensure_admins(
164
+ db: DbSessionFactory,
165
+ *,
166
+ email_sender: Optional[WelcomeEmailSender] = None,
167
+ ) -> None:
168
+ """
169
+ Ensure that all startup admin users are present in the database. If any are missing, they will
170
+ be added. Existing records will not be modified.
171
+ """
172
+ if not (admins := get_env_admins()):
173
+ return
174
+ disable_basic_auth = get_env_disable_basic_auth()
175
+ async with db() as session:
176
+ existing_emails = set(
177
+ await session.scalars(
178
+ sa.select(models.User.email).where(models.User.email.in_(admins.keys()))
179
+ )
180
+ )
181
+ admins = {
182
+ email: username for email, username in admins.items() if email not in existing_emails
183
+ }
184
+ if not admins:
185
+ return
186
+ existing_usernames = set(
187
+ await session.scalars(
188
+ sa.select(models.User.username).where(models.User.username.in_(admins.values()))
189
+ )
190
+ )
191
+ admins = {
192
+ email: username
193
+ for email, username in admins.items()
194
+ if username not in existing_usernames
195
+ }
196
+ if not admins:
197
+ return
198
+ admin_role_id = await session.scalar(sa.select(models.UserRole.id).filter_by(name="ADMIN"))
199
+ assert admin_role_id is not None, "Admin role not found in database"
200
+ user: models.User
201
+ for email, username in admins.items():
202
+ if not disable_basic_auth:
203
+ user = models.LocalUser(
204
+ email=email,
205
+ username=username,
206
+ password_salt=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
207
+ password_hash=secrets.token_bytes(DEFAULT_SECRET_LENGTH),
208
+ )
209
+ else:
210
+ user = models.OAuth2User(
211
+ email=email,
212
+ username=username,
213
+ )
214
+ user.user_role_id = admin_role_id
215
+ session.add(user)
216
+ await session.flush()
217
+ if email_sender is None:
218
+ return
219
+ for exc in await gather(
220
+ *(email_sender.send_welcome_email(email, username) for email, username in admins.items()),
221
+ return_exceptions=True,
222
+ ):
223
+ if isinstance(exc, Exception):
224
+ logger.error(f"Failed to send welcome email: {exc}")
225
+
226
+
227
+ _CHILDLESS_RECORD_DELETION_GRACE_PERIOD_DAYS = 1
228
+
229
+
230
+ def _stmt_to_delete_expired_childless_records(
231
+ table: type[models.Base],
232
+ foreign_key: Union[InstrumentedAttribute[int], InstrumentedAttribute[Optional[int]]],
233
+ ) -> ReturningDelete[tuple[int]]:
234
+ """
235
+ Creates a SQLAlchemy DELETE statement to permanently remove childless records.
236
+
237
+ Args:
238
+ table: The table model class that has a deleted_at column
239
+ foreign_key: The foreign key attribute to check for child relationships
240
+
241
+ Returns:
242
+ A DELETE statement that removes childless records marked for deletion more than
243
+ _CHILDLESS_RECORD_DELETION_GRACE_PERIOD_DAYS days ago
244
+ """ # noqa: E501
245
+ if not hasattr(table, "deleted_at"):
246
+ raise TypeError("Table must have a 'deleted_at' column")
247
+ cutoff_time = datetime.now(timezone.utc) - timedelta(
248
+ days=_CHILDLESS_RECORD_DELETION_GRACE_PERIOD_DAYS
249
+ )
250
+ return (
251
+ sa.delete(table)
252
+ .where(table.deleted_at.isnot(None))
253
+ .where(table.deleted_at < cutoff_time)
254
+ .where(~sa.exists().where(table.id == foreign_key))
255
+ .returning(table.id)
256
+ )
257
+
258
+
259
+ async def _delete_expired_childless_records_on_generative_models(
260
+ db: DbSessionFactory,
261
+ ) -> None:
262
+ """
263
+ Permanently deletes childless GenerativeModel records that have been marked for deletion.
264
+
265
+ This function removes GenerativeModel records that:
266
+ - Have been marked for deletion (deleted_at is not NULL)
267
+ - Were marked more than 1 day ago (grace period expired)
268
+ - Have no associated SpanCost records (childless)
269
+
270
+ This cleanup is necessary to remove orphaned records that may have been left behind
271
+ due to previous migrations or deletions.
272
+ """ # noqa: E501
273
+ stmt = _stmt_to_delete_expired_childless_records(
274
+ models.GenerativeModel,
275
+ models.SpanCost.model_id,
276
+ )
277
+ async with db() as session:
278
+ result = (await session.scalars(stmt)).all()
279
+ if result:
280
+ logger.info(f"Permanently deleted {len(result)} expired childless GenerativeModel records")
281
+ else:
282
+ logger.debug("No expired childless GenerativeModel records found for permanent deletion")
283
+
284
+
285
+ async def _delete_expired_childless_records(
286
+ db: DbSessionFactory,
287
+ ) -> None:
288
+ """
289
+ Permanently deletes childless records across all relevant tables.
290
+
291
+ This function runs the deletion process for all table types that support soft deletion,
292
+ handling any exceptions that occur during the process. Only records that have been
293
+ marked for deletion for more than the grace period (1 day) are permanently removed.
294
+ """ # noqa: E501
295
+ exceptions = await gather(
296
+ _delete_expired_childless_records_on_generative_models(db),
297
+ return_exceptions=True,
298
+ )
299
+ for exc in exceptions:
300
+ if isinstance(exc, Exception):
301
+ logger.error(f"Failed to delete childless records: {exc}")
302
+
303
+
304
+ async def _ensure_default_project_trace_retention_policy(db: DbSessionFactory) -> None:
305
+ """
306
+ Ensures the default trace retention policy (id=1) exists in the database. Default policy
307
+ applies to all projects without a specific policy (i.e. foreign key is null).
308
+
309
+ This function checks for the presence of the default trace retention policy and
310
+ creates it if missing. The default trace retention policy:
311
+
312
+ - Has ID=0
313
+ - Is named "Default"
314
+ - Runs every Sunday at midnight UTC (cron: "0 0 * * 0")
315
+ - Retains traces indefinitely
316
+
317
+ If the default policy already exists, this function makes no changes.
318
+
319
+ Args:
320
+ db (DbSessionFactory): An async SQLAlchemy session factory.
321
+
322
+ Returns:
323
+ None
324
+ """
325
+ assert DEFAULT_PROJECT_TRACE_RETENTION_POLICY_ID == 0
326
+ async with db() as session:
327
+ if await session.scalar(
328
+ sa.select(
329
+ sa.exists().where(
330
+ models.ProjectTraceRetentionPolicy.id
331
+ == DEFAULT_PROJECT_TRACE_RETENTION_POLICY_ID
332
+ )
333
+ )
334
+ ):
335
+ return
336
+ cron_expression = TraceRetentionCronExpression(root="0 0 * * 0")
337
+ rule = TraceRetentionRule(root=MaxDaysRule(max_days=0))
338
+ await session.execute(
339
+ sa.insert(models.ProjectTraceRetentionPolicy),
340
+ [
341
+ {
342
+ "id": DEFAULT_PROJECT_TRACE_RETENTION_POLICY_ID,
343
+ "name": "Default",
344
+ "cron_expression": cron_expression,
345
+ "rule": rule,
346
+ }
347
+ ],
348
+ )
349
+
350
+
351
+ _COST_MODEL_MANIFEST: Path = (
352
+ Path(__file__).parent.parent / "server" / "cost_tracking" / "model_cost_manifest.json"
353
+ )
354
+
355
+
356
+ class _TokenTypeKey(NamedTuple):
357
+ """
358
+ Composite key for uniquely identifying token price configurations.
359
+
360
+ Token prices are differentiated by both their type (e.g., "input", "output", "audio")
361
+ and whether they represent prompt tokens (input to the model) or completion tokens
362
+ (output from the model). Some token types like "audio" can exist in both categories.
363
+
364
+ Attributes:
365
+ token_type: The category of token (e.g., "input", "output", "audio", "cache_write")
366
+ is_prompt: True if these are prompt/input tokens, False if completion/output tokens
367
+ """
368
+
369
+ token_type: str
370
+ is_prompt: bool
371
+
372
+
373
+ async def _ensure_model_costs(db: DbSessionFactory) -> None:
374
+ """
375
+ Ensures that built-in generative models and their token pricing information are up-to-date
376
+ in the database based on the model cost manifest file.
377
+
378
+ This function performs a comprehensive synchronization between the database and the manifest:
379
+
380
+ 1. **Model Management**: Creates new built-in models from the manifest or updates existing ones
381
+ 2. **Token Price Synchronization**: Ensures all token prices match the manifest rates
382
+ 3. **Cleanup**: Soft-deletes built-in models no longer present in the manifest
383
+
384
+ The function handles different token types including:
385
+ - Input tokens (prompt): Standard input tokens for generation
386
+ - Cache write tokens (prompt): Tokens written to cache systems
387
+ - Cache read tokens (prompt): Tokens read from cache systems
388
+ - Output tokens (non-prompt): Generated response tokens
389
+ - Audio tokens (both prompt and non-prompt): Audio processing tokens
390
+
391
+ Token prices are uniquely identified by (token_type, is_prompt) pairs to handle
392
+ cases like audio tokens that can be both prompt and non-prompt.
393
+
394
+ Args:
395
+ db (DbSessionFactory): Database session factory for database operations
396
+
397
+ Returns:
398
+ None
399
+
400
+ Raises:
401
+ FileNotFoundError: If the model cost manifest file is not found
402
+ json.JSONDecodeError: If the manifest file contains invalid JSON
403
+ ValueError: If manifest data is malformed or missing required fields
404
+ """
405
+ # Load the authoritative model cost data from the manifest file
406
+ with open(_COST_MODEL_MANIFEST) as f:
407
+ manifest = json.load(f)
408
+
409
+ # Define all supported token types with their prompt/non-prompt classification
410
+ # This determines how tokens are categorized for billing purposes
411
+ token_types: list[_TokenTypeKey] = [
412
+ _TokenTypeKey("input", True), # Standard input tokens
413
+ _TokenTypeKey("cache_write", True), # Tokens written to cache
414
+ _TokenTypeKey("cache_read", True), # Tokens read from cache
415
+ _TokenTypeKey("output", False), # Generated output tokens
416
+ _TokenTypeKey("audio", True), # Audio input tokens
417
+ _TokenTypeKey("audio", False), # Audio output tokens
418
+ ]
419
+
420
+ async with db() as session:
421
+ # Fetch all existing built-in models with their token prices eagerly loaded
422
+ # Using .unique() to deduplicate models when multiple token prices are joined
423
+ built_in_models = {
424
+ omodel.name: omodel
425
+ for omodel in (
426
+ await session.scalars(
427
+ select(models.GenerativeModel)
428
+ .where(models.GenerativeModel.deleted_at.is_(None))
429
+ .where(models.GenerativeModel.is_built_in.is_(True))
430
+ .options(joinedload(models.GenerativeModel.token_prices))
431
+ )
432
+ ).unique()
433
+ }
434
+
435
+ seen_names: set[str] = set()
436
+ seen_patterns: set[tuple[re.Pattern[str], str]] = set()
437
+
438
+ # Process each model in the manifest
439
+ for model_data in manifest:
440
+ name = str(model_data.get("model") or "").strip()
441
+ if not name:
442
+ logger.warning("Skipping model with empty name in manifest")
443
+ continue
444
+ if name in seen_names:
445
+ logger.warning(f"Skipping model '{name}' with duplicate name in manifest")
446
+ continue
447
+ seen_names.add(name)
448
+ regex = str(model_data.get("regex") or "").strip()
449
+ try:
450
+ pattern = re.compile(regex)
451
+ except re.error as e:
452
+ logger.warning(f"Skipping model '{name}' with invalid regex: {e}")
453
+ continue
454
+ provider = str(model_data.get("provider") or "").strip()
455
+ if (pattern, provider) in seen_patterns:
456
+ logger.warning(
457
+ f"Skipping model '{name}' with duplicate name_pattern/provider combination"
458
+ )
459
+ continue
460
+ seen_patterns.add((pattern, provider))
461
+ # Remove model from built_in_models dict (for cleanup tracking)
462
+ # or create new model if not found
463
+ model = built_in_models.pop(model_data["model"], None)
464
+ if model is None:
465
+ # Create new built-in model from manifest data
466
+ model = models.GenerativeModel(
467
+ name=name,
468
+ provider=provider,
469
+ name_pattern=pattern,
470
+ is_built_in=True,
471
+ )
472
+ session.add(model)
473
+ else:
474
+ # Update existing model's metadata from manifest
475
+ model.provider = provider
476
+ model.name_pattern = pattern
477
+
478
+ # Create lookup table for existing token prices by (token_type, is_prompt)
479
+ # Using pop() during iteration allows us to track which prices are no longer needed
480
+ token_prices = {
481
+ _TokenTypeKey(token_price.token_type, token_price.is_prompt): token_price
482
+ for token_price in model.token_prices
483
+ }
484
+
485
+ # Synchronize token prices for all supported token types
486
+ for token_type, is_prompt in token_types:
487
+ # Skip if this token type has no rate in the manifest
488
+ if not (base_rate := model_data.get(token_type)):
489
+ continue
490
+
491
+ key = _TokenTypeKey(token_type, is_prompt)
492
+ # Remove from tracking dict and get existing price (if any)
493
+ if not (token_price := token_prices.pop(key, None)):
494
+ # Create new token price if it doesn't exist
495
+ token_price = models.TokenPrice(
496
+ token_type=token_type,
497
+ is_prompt=is_prompt,
498
+ base_rate=base_rate,
499
+ )
500
+ model.token_prices.append(token_price)
501
+ elif token_price.base_rate != base_rate:
502
+ # Update existing price if rate has changed
503
+ token_price.base_rate = base_rate
504
+
505
+ # Remove any token prices that are no longer in the manifest
506
+ # These are prices that weren't popped from the token_prices dict above
507
+ for token_price in token_prices.values():
508
+ model.token_prices.remove(token_price)
509
+
510
+ # Clean up built-in models that are no longer in the manifest
511
+ # These are models that weren't popped from built_in_models dict above
512
+ remaining_models = list(built_in_models.values())
513
+ if not remaining_models:
514
+ return
515
+
516
+ # Soft delete obsolete built-in models
517
+ async with db() as session:
518
+ await session.execute(
519
+ sa.update(models.GenerativeModel)
520
+ .values(deleted_at=sa.func.now())
521
+ .where(models.GenerativeModel.id.in_([m.id for m in remaining_models]))
522
+ )