arize-phoenix 9.4.0__tar.gz → 9.6.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 (406) hide show
  1. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/PKG-INFO +4 -4
  2. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/pyproject.toml +5 -3
  3. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/README.md +1 -1
  4. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/functions.py +11 -2
  5. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/playground_clients.py +1 -1
  6. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/datasets.py +11 -3
  7. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Project.py +126 -5
  8. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Span.py +49 -0
  9. arize_phoenix-9.6.0/src/phoenix/server/api/types/TokenCountPromptDetails.py +10 -0
  10. arize_phoenix-9.6.0/src/phoenix/server/cost_tracking/cost_lookup.py +255 -0
  11. arize_phoenix-9.6.0/src/phoenix/server/cost_tracking/model_cost_manifest.json +830 -0
  12. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/main.py +1 -1
  13. arize_phoenix-9.6.0/src/phoenix/server/static/.vite/manifest.json +87 -0
  14. arize_phoenix-9.4.0/src/phoenix/server/static/assets/components-DIphpoYn.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/components-BqMUivPb.js +187 -190
  15. arize_phoenix-9.4.0/src/phoenix/server/static/assets/index-RiEaQhz1.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/index-B6aQZkI9.js +20 -11
  16. arize_phoenix-9.4.0/src/phoenix/server/static/assets/pages-BPhRdaQm.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/pages-C9XLSuBO.js +800 -674
  17. arize_phoenix-9.4.0/src/phoenix/server/static/assets/vendor-BbE93T2A.css → arize_phoenix-9.6.0/src/phoenix/server/static/assets/vendor-WIZid84E.css +1 -1
  18. arize_phoenix-9.4.0/src/phoenix/server/static/assets/vendor-arizeai-CGce5406.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/vendor-arizeai-BhbMHqQs.js +1 -1
  19. arize_phoenix-9.4.0/src/phoenix/server/static/assets/vendor-codemirror-KgXtr1rz.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/vendor-codemirror-CeLHFooz.js +1 -1
  20. arize_phoenix-9.4.0/src/phoenix/server/static/assets/vendor-recharts-Cm-8_DB9.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/vendor-recharts-PlWJHgM9.js +2 -2
  21. arize_phoenix-9.4.0/src/phoenix/server/static/assets/vendor-shiki-BsLqKLvc.js → arize_phoenix-9.6.0/src/phoenix/server/static/assets/vendor-shiki-CPwL2jwA.js +1 -1
  22. arize_phoenix-9.6.0/src/phoenix/utilities/span_store.py +0 -0
  23. arize_phoenix-9.6.0/src/phoenix/version.py +1 -0
  24. arize_phoenix-9.4.0/src/phoenix/server/static/.vite/manifest.json +0 -87
  25. arize_phoenix-9.4.0/src/phoenix/version.py +0 -1
  26. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/.gitignore +0 -0
  27. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/IP_NOTICE +0 -0
  28. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/LICENSE +0 -0
  29. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/README.md +0 -0
  30. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/__init__.py +0 -0
  31. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/auth.py +0 -0
  32. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/config.py +0 -0
  33. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/core/__init__.py +0 -0
  34. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/core/embedding_dimension.py +0 -0
  35. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/core/model.py +0 -0
  36. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/core/model_schema.py +0 -0
  37. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  38. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/datetime_utils.py +0 -0
  39. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/__init__.py +0 -0
  40. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/alembic.ini +0 -0
  41. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/bulk_inserter.py +0 -0
  42. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/constants.py +0 -0
  43. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/engines.py +0 -0
  44. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/enums.py +0 -0
  45. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/facilitator.py +0 -0
  46. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/helpers.py +0 -0
  47. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/__init__.py +0 -0
  48. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/constants.py +0 -0
  49. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/dataset.py +0 -0
  50. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/document_annotation.py +0 -0
  51. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/evaluation.py +0 -0
  52. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/helpers.py +0 -0
  53. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/span.py +0 -0
  54. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/span_annotation.py +0 -0
  55. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/trace_annotation.py +0 -0
  56. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/insertion/types.py +0 -0
  57. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrate.py +0 -0
  58. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/__init__.py +0 -0
  59. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/data_migration_scripts/__init__.py +0 -0
  60. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/data_migration_scripts/populate_project_sessions.py +0 -0
  61. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/env.py +0 -0
  62. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/script.py.mako +0 -0
  63. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  64. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/2f9d1a65945f_annotation_config_migration.py +0 -0
  65. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +0 -0
  66. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/4ded9e43755f_create_project_sessions_table.py +0 -0
  67. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/8a3764fe7f1a_change_jsonb_to_json_for_prompts.py +0 -0
  68. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/bb8139330879_create_project_trace_retention_policies_table.py +0 -0
  69. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/bc8fea3c2bc8_add_prompt_tables.py +0 -0
  70. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/cd164e83824f_users_and_tokens.py +0 -0
  71. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  72. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/models.py +0 -0
  73. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/pg_config.py +0 -0
  74. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/types/__init__.py +0 -0
  75. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/types/annotation_configs.py +0 -0
  76. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/types/db_models.py +0 -0
  77. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/types/identifier.py +0 -0
  78. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/types/model_provider.py +0 -0
  79. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/db/types/trace_retention.py +0 -0
  80. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/exceptions.py +0 -0
  81. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/__init__.py +0 -0
  82. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  83. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/evaluators/base.py +0 -0
  84. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  85. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  86. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
  87. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/tracing.py +0 -0
  88. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/types.py +0 -0
  89. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/experiments/utils.py +0 -0
  90. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/inferences/__init__.py +0 -0
  91. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/inferences/errors.py +0 -0
  92. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/inferences/fixtures.py +0 -0
  93. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/inferences/inferences.py +0 -0
  94. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/inferences/schema.py +0 -0
  95. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/inferences/validation.py +0 -0
  96. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/logging/__init__.py +0 -0
  97. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/logging/_config.py +0 -0
  98. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/logging/_filter.py +0 -0
  99. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/logging/_formatter.py +0 -0
  100. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/README.md +0 -0
  101. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/__init__.py +0 -0
  102. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/binning.py +0 -0
  103. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/metrics.py +0 -0
  104. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/mixins.py +0 -0
  105. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  106. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/timeseries.py +0 -0
  107. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/metrics/wrappers.py +0 -0
  108. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/pointcloud/__init__.py +0 -0
  109. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/pointcloud/clustering.py +0 -0
  110. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  111. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/pointcloud/projectors.py +0 -0
  112. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  113. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/py.typed +0 -0
  114. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/__init__.py +0 -0
  115. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/README.md +0 -0
  116. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/__init__.py +0 -0
  117. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/auth.py +0 -0
  118. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/context.py +0 -0
  119. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/__init__.py +0 -0
  120. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  121. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  122. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  123. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  124. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  125. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  126. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  127. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  128. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  129. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  130. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  131. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/experiment_run_annotations.py +0 -0
  132. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  133. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  134. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  135. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  136. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/num_child_spans.py +0 -0
  137. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/num_spans_per_trace.py +0 -0
  138. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  139. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/project_ids_by_trace_retention_policy_id.py +0 -0
  140. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/prompt_version_sequence_number.py +0 -0
  141. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  142. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/session_io.py +0 -0
  143. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/session_num_traces.py +0 -0
  144. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/session_num_traces_with_error.py +0 -0
  145. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/session_token_usages.py +0 -0
  146. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/session_trace_latency_ms_quantile.py +0 -0
  147. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  148. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/span_by_id.py +0 -0
  149. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  150. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  151. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  152. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/table_fields.py +0 -0
  153. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  154. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/trace_by_trace_ids.py +0 -0
  155. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/trace_retention_policy_id_by_project_id.py +0 -0
  156. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/trace_root_spans.py +0 -0
  157. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/user_roles.py +0 -0
  158. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/dataloaders/users.py +0 -0
  159. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/exceptions.py +0 -0
  160. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
  161. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/annotations.py +0 -0
  162. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  163. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/experiment_run_filters.py +0 -0
  164. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/playground_registry.py +0 -0
  165. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/playground_spans.py +0 -0
  166. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/prompts/__init__.py +0 -0
  167. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/prompts/conversions/__init__.py +0 -0
  168. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/prompts/conversions/anthropic.py +0 -0
  169. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/prompts/conversions/openai.py +0 -0
  170. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/helpers/prompts/models.py +0 -0
  171. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  172. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  173. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ChatCompletionInput.py +0 -0
  174. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ChatCompletionMessageInput.py +0 -0
  175. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  176. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  177. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  178. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  179. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  180. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  181. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  182. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  183. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  184. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  185. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  186. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  187. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  188. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  189. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  190. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  191. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/GenerativeModelInput.py +0 -0
  192. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  193. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/InvocationParameters.py +0 -0
  194. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  195. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  196. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  197. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  198. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ProjectFilter.py +0 -0
  199. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ProjectSessionSort.py +0 -0
  200. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/ProjectSort.py +0 -0
  201. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/PromptTemplateOptions.py +0 -0
  202. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/PromptVersionInput.py +0 -0
  203. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/SpanAnnotationFilter.py +0 -0
  204. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  205. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  206. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  207. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  208. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/UserRoleInput.py +0 -0
  209. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
  210. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/interceptor.py +0 -0
  211. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/__init__.py +0 -0
  212. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/annotation_config_mutations.py +0 -0
  213. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/api_key_mutations.py +0 -0
  214. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/chat_mutations.py +0 -0
  215. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
  216. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
  217. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  218. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
  219. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/project_trace_retention_policy_mutations.py +0 -0
  220. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/prompt_label_mutations.py +0 -0
  221. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/prompt_mutations.py +0 -0
  222. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/prompt_version_tag_mutations.py +0 -0
  223. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +0 -0
  224. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +0 -0
  225. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/trace_mutations.py +0 -0
  226. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/mutations/user_mutations.py +0 -0
  227. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/openapi/__init__.py +0 -0
  228. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/openapi/main.py +0 -0
  229. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/openapi/schema.py +0 -0
  230. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/queries.py +0 -0
  231. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/__init__.py +0 -0
  232. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/auth.py +0 -0
  233. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/embeddings.py +0 -0
  234. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/oauth2.py +0 -0
  235. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/utils.py +0 -0
  236. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/__init__.py +0 -0
  237. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/annotation_configs.py +0 -0
  238. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/annotations.py +0 -0
  239. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  240. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -0
  241. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -0
  242. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/experiments.py +0 -0
  243. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/models.py +0 -0
  244. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/projects.py +0 -0
  245. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/prompts.py +0 -0
  246. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/spans.py +0 -0
  247. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/traces.py +0 -0
  248. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  249. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/schema.py +0 -0
  250. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/subscriptions.py +0 -0
  251. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Annotation.py +0 -0
  252. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/AnnotationConfig.py +0 -0
  253. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/AnnotationSource.py +0 -0
  254. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  255. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  256. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ApiKey.py +0 -0
  257. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/AuthMethod.py +0 -0
  258. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ChatCompletionMessageRole.py +0 -0
  259. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +0 -0
  260. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  261. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  262. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/CronExpression.py +0 -0
  263. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  264. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  265. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  266. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  267. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  268. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  269. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  270. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  271. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  272. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  273. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  274. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  275. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  276. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  277. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  278. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
  279. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  280. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Event.py +0 -0
  281. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  282. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  283. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Experiment.py +0 -0
  284. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  285. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  286. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
  287. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  288. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  289. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  290. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/GenerativeModel.py +0 -0
  291. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/GenerativeProvider.py +0 -0
  292. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Identifier.py +0 -0
  293. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Inferences.py +0 -0
  294. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  295. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  296. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  297. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Model.py +0 -0
  298. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  299. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  300. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ProjectSession.py +0 -0
  301. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ProjectTraceRetentionPolicy.py +0 -0
  302. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Prompt.py +0 -0
  303. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/PromptLabel.py +0 -0
  304. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  305. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/PromptVersion.py +0 -0
  306. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/PromptVersionTag.py +0 -0
  307. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/PromptVersionTemplate.py +0 -0
  308. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ResponseFormat.py +0 -0
  309. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  310. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  311. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Segments.py +0 -0
  312. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  313. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  314. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/SpanIOValue.py +0 -0
  315. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/SystemApiKey.py +0 -0
  316. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  317. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/TokenUsage.py +0 -0
  318. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ToolDefinition.py +0 -0
  319. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/Trace.py +0 -0
  320. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  321. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  322. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/User.py +0 -0
  323. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/UserApiKey.py +0 -0
  324. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/UserRole.py +0 -0
  325. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  326. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  327. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/__init__.py +0 -0
  328. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/node.py +0 -0
  329. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/types/pagination.py +0 -0
  330. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/api/utils.py +0 -0
  331. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/app.py +0 -0
  332. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/authorization.py +0 -0
  333. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/bearer_auth.py +0 -0
  334. {arize_phoenix-9.4.0/src/phoenix/server/email → arize_phoenix-9.6.0/src/phoenix/server/cost_tracking}/__init__.py +0 -0
  335. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/dml_event.py +0 -0
  336. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/dml_event_handler.py +0 -0
  337. {arize_phoenix-9.4.0/src/phoenix/server/email/templates → arize_phoenix-9.6.0/src/phoenix/server/email}/__init__.py +0 -0
  338. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/email/sender.py +0 -0
  339. {arize_phoenix-9.4.0/src/phoenix/server/middleware → arize_phoenix-9.6.0/src/phoenix/server/email/templates}/__init__.py +0 -0
  340. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/email/templates/password_reset.html +0 -0
  341. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/email/templates/welcome.html +0 -0
  342. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/email/types.py +0 -0
  343. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/grpc_server.py +0 -0
  344. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/jwt_store.py +0 -0
  345. {arize_phoenix-9.4.0/src/phoenix/server/openapi → arize_phoenix-9.6.0/src/phoenix/server/middleware}/__init__.py +0 -0
  346. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/middleware/gzip.py +0 -0
  347. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/oauth2.py +0 -0
  348. {arize_phoenix-9.4.0/src/phoenix/server/templates → arize_phoenix-9.6.0/src/phoenix/server/openapi}/__init__.py +0 -0
  349. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/prometheus.py +0 -0
  350. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/rate_limiters.py +0 -0
  351. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/retention.py +0 -0
  352. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  353. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  354. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  355. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  356. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  357. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  358. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  359. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  360. /arize_phoenix-9.4.0/src/phoenix/server/static/assets/vendor-CHbwJtRJ.js → /arize_phoenix-9.6.0/src/phoenix/server/static/assets/vendor-CToBXdDM.js +0 -0
  361. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/assets/vendor-three-C5WAXd5r.js +0 -0
  362. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/favicon.ico +0 -0
  363. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/static/modernizr.js +0 -0
  364. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/telemetry.py +0 -0
  365. {arize_phoenix-9.4.0/src/phoenix/session → arize_phoenix-9.6.0/src/phoenix/server/templates}/__init__.py +0 -0
  366. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/templates/index.html +0 -0
  367. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/thread_server.py +0 -0
  368. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/server/types.py +0 -0
  369. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/services.py +0 -0
  370. /arize_phoenix-9.4.0/src/phoenix/utilities/span_store.py → /arize_phoenix-9.6.0/src/phoenix/session/__init__.py +0 -0
  371. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/session/client.py +0 -0
  372. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/session/data_extractor.py +0 -0
  373. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/session/evaluation.py +0 -0
  374. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/session/session.py +0 -0
  375. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/settings.py +0 -0
  376. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/__init__.py +0 -0
  377. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/attributes.py +0 -0
  378. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/dsl/README.md +0 -0
  379. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  380. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/dsl/filter.py +0 -0
  381. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  382. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/dsl/query.py +0 -0
  383. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/errors.py +0 -0
  384. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  385. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/exporter.py +0 -0
  386. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/fixtures.py +0 -0
  387. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/otel.py +0 -0
  388. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/projects.py +0 -0
  389. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/schemas.py +0 -0
  390. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/span_evaluations.py +0 -0
  391. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  392. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  393. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/trace_dataset.py +0 -0
  394. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/utils.py +0 -0
  395. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/v1/__init__.py +0 -0
  396. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  397. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  398. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/__init__.py +0 -0
  399. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/client.py +0 -0
  400. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/deprecation.py +0 -0
  401. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/error_handling.py +0 -0
  402. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/json.py +0 -0
  403. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/logging.py +0 -0
  404. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/project.py +0 -0
  405. {arize_phoenix-9.4.0 → arize_phoenix-9.6.0}/src/phoenix/utilities/re.py +0 -0
  406. {arize_phoenix-9.4.0 → arize_phoenix-9.6.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: 9.4.0
3
+ Version: 9.6.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
@@ -49,7 +49,7 @@ Requires-Dist: scipy
49
49
  Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
50
50
  Requires-Dist: sqlean-py>=3.45.1
51
51
  Requires-Dist: starlette
52
- Requires-Dist: strawberry-graphql==0.267.0
52
+ Requires-Dist: strawberry-graphql==0.269.0
53
53
  Requires-Dist: tqdm
54
54
  Requires-Dist: typing-extensions>=4.6
55
55
  Requires-Dist: uvicorn
@@ -71,7 +71,7 @@ Requires-Dist: opentelemetry-sdk; extra == 'container'
71
71
  Requires-Dist: opentelemetry-semantic-conventions; extra == 'container'
72
72
  Requires-Dist: prometheus-client; extra == 'container'
73
73
  Requires-Dist: py-grpc-prometheus; extra == 'container'
74
- Requires-Dist: strawberry-graphql[opentelemetry]==0.267.0; extra == 'container'
74
+ Requires-Dist: strawberry-graphql[opentelemetry]==0.269.0; extra == 'container'
75
75
  Requires-Dist: umap-learn; extra == 'container'
76
76
  Requires-Dist: uvloop; (platform_system != 'Windows') and extra == 'container'
77
77
  Provides-Extra: dev
@@ -102,7 +102,7 @@ Requires-Dist: pytest-postgresql; extra == 'dev'
102
102
  Requires-Dist: pytest-xdist; extra == 'dev'
103
103
  Requires-Dist: pytest==8.3.3; extra == 'dev'
104
104
  Requires-Dist: ruff==0.6.9; extra == 'dev'
105
- Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.267.0; extra == 'dev'
105
+ Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.269.0; extra == 'dev'
106
106
  Requires-Dist: tabulate; extra == 'dev'
107
107
  Requires-Dist: tox-uv==1.11.3; extra == 'dev'
108
108
  Requires-Dist: tox==4.18.1; extra == 'dev'
@@ -29,7 +29,7 @@ dependencies = [
29
29
  "starlette",
30
30
  "uvicorn",
31
31
  "psutil",
32
- "strawberry-graphql==0.267.0", # avoid this issue: https://github.com/strawberry-graphql/strawberry/issues/3854
32
+ "strawberry-graphql==0.269.0", # fix relay ids
33
33
  "pyarrow",
34
34
  "typing-extensions>=4.6",
35
35
  "scipy",
@@ -88,7 +88,7 @@ dev = [
88
88
  "pytest-postgresql",
89
89
  "asyncpg",
90
90
  "psycopg[binary,pool]",
91
- "strawberry-graphql[debug-server,opentelemetry]==0.267.0", # avoid this issue: https://github.com/strawberry-graphql/strawberry/issues/3854
91
+ "strawberry-graphql[debug-server,opentelemetry]==0.269.0", # fix relay ids
92
92
  "pre-commit",
93
93
  "arize[AutoEmbeddings, LLM_Evaluation]",
94
94
  "llama-index>=0.10.3",
@@ -137,7 +137,7 @@ container = [
137
137
  "opentelemetry-instrumentation-sqlalchemy",
138
138
  "opentelemetry-instrumentation-grpc",
139
139
  "py-grpc-prometheus",
140
- "strawberry-graphql[opentelemetry]==0.267.0", # avoid this issue: https://github.com/strawberry-graphql/strawberry/issues/3854
140
+ "strawberry-graphql[opentelemetry]==0.269.0", # fix relay ids
141
141
  "uvloop; platform_system != 'Windows'",
142
142
  "fast-hdbscan>=0.2.0",
143
143
  "numba>=0.60.0", # https://github.com/astral-sh/uv/issues/6281
@@ -168,6 +168,7 @@ exclude = [
168
168
  artifacts = [
169
169
  "src/phoenix/server/static",
170
170
  "src/phoenix/db/migrations",
171
+ "src/phoenix/server/cost_tracking/model_cost_manifest.json",
171
172
  ]
172
173
 
173
174
  [tool.hatch.build]
@@ -187,6 +188,7 @@ exclude = [
187
188
  artifacts = [
188
189
  "src/phoenix/server/static",
189
190
  "src/phoenix/db/migrations",
191
+ "src/phoenix/server/cost_tracking/model_cost_manifest.json",
190
192
  ]
191
193
 
192
194
  [tool.pytest.ini_options]
@@ -37,7 +37,7 @@ alembic upgrade head
37
37
 
38
38
  If the above command fails, it may be necessary to undo partially applied changes from a failed migration by first running down-migrations. This can be accomplished by identifying the ID of the migration revision you wish to return to. Revisions are defined [here](./migrations/versions/).
39
39
 
40
- ⚠️ Running down-migrations can result in lost data. Only run down-migrations if you know what you are doing and consider backing up your database first. If you have any questions or doubts, contact the Phoenix team in the `#phoenix-support` channel of the [Arize AI Slack community](https://join.slack.com/t/arize-ai/shared_invite/zt-1px8dcmlf-fmThhDFD_V_48oU7ALan4Q) or via GitHub.
40
+ ⚠️ Running down-migrations can result in lost data. Only run down-migrations if you know what you are doing and consider backing up your database first. If you have any questions or doubts, contact the Phoenix team in the `#phoenix-support` channel of the [Arize AI Slack community](https://arize-ai.slack.com/join/shared_invite/zt-2w57bhem8-hq24MB6u7yE_ZF_ilOYSBw#/shared-invite/email) or via GitHub.
41
41
 
42
42
  ```bash
43
43
  alembic downgrade <revision-id>
@@ -116,8 +116,17 @@ def run_experiment(
116
116
  - `metadata`: Metadata associated with the dataset example
117
117
  - `example`: The dataset `Example` object with all associated fields
118
118
 
119
- An `evaluator` is either a synchronous or asynchronous function that returns either a boolean
120
- or numeric "score". If the `evaluator` is a function of one argument then that argument will be
119
+ An `evaluator` is either a synchronous or asynchronous function that returns an evaluation
120
+ result object, which can take any of the following forms.
121
+
122
+ - phoenix.experiments.types.EvaluationResult with optional fields for score, label, explanation
123
+ and metadata
124
+ - a `bool`, which will be interpreted as a score of 0 or 1 plus a label of "True" or "False"
125
+ - a `float`, which will be interpreted as a score
126
+ - a `str`, which will be interpreted as a label
127
+ - a 2-`tuple` of (`float`, `str`), which will be interpreted as (score, explanation)
128
+
129
+ If the `evaluator` is a function of one argument then that argument will be
121
130
  bound to the `output` of the task. Alternatively, the `evaluator` can be a function of any
122
131
  combination of specific argument names that will be bound to special values:
123
132
 
@@ -701,7 +701,7 @@ class AzureOpenAIStreamingClient(OpenAIBaseStreamingClient):
701
701
  provider_key=GenerativeProviderKey.ANTHROPIC,
702
702
  model_names=[
703
703
  PROVIDER_DEFAULT,
704
- "claude-3-7-latest",
704
+ "claude-3-7-sonnet-latest",
705
705
  "claude-3-7-sonnet-20250219",
706
706
  "claude-3-5-sonnet-latest",
707
707
  "claude-3-5-haiku-latest",
@@ -3,6 +3,7 @@ import gzip
3
3
  import io
4
4
  import json
5
5
  import logging
6
+ import urllib
6
7
  import zlib
7
8
  from asyncio import QueueFull
8
9
  from collections import Counter
@@ -817,10 +818,11 @@ async def get_dataset_csv(
817
818
  except ValueError as e:
818
819
  raise HTTPException(detail=str(e), status_code=HTTP_422_UNPROCESSABLE_ENTITY)
819
820
  content = await run_in_threadpool(_get_content_csv, examples)
821
+ encoded_dataset_name = urllib.parse.quote(dataset_name)
820
822
  return Response(
821
823
  content=content,
822
824
  headers={
823
- "content-disposition": f'attachment; filename="{dataset_name}.csv"',
825
+ "content-disposition": f"attachment; filename*=UTF-8''{encoded_dataset_name}.csv",
824
826
  "content-type": "text/csv",
825
827
  },
826
828
  )
@@ -859,7 +861,10 @@ async def get_dataset_jsonl_openai_ft(
859
861
  except ValueError as e:
860
862
  raise HTTPException(detail=str(e), status_code=HTTP_422_UNPROCESSABLE_ENTITY)
861
863
  content = await run_in_threadpool(_get_content_jsonl_openai_ft, examples)
862
- response.headers["content-disposition"] = f'attachment; filename="{dataset_name}.jsonl"'
864
+ encoded_dataset_name = urllib.parse.quote(dataset_name)
865
+ response.headers["content-disposition"] = (
866
+ f"attachment; filename*=UTF-8''{encoded_dataset_name}.jsonl"
867
+ )
863
868
  return content
864
869
 
865
870
 
@@ -896,7 +901,10 @@ async def get_dataset_jsonl_openai_evals(
896
901
  except ValueError as e:
897
902
  raise HTTPException(detail=str(e), status_code=HTTP_422_UNPROCESSABLE_ENTITY)
898
903
  content = await run_in_threadpool(_get_content_jsonl_openai_evals, examples)
899
- response.headers["content-disposition"] = f'attachment; filename="{dataset_name}.jsonl"'
904
+ encoded_dataset_name = urllib.parse.quote(dataset_name)
905
+ response.headers["content-disposition"] = (
906
+ f"attachment; filename*=UTF-8''{encoded_dataset_name}.jsonl"
907
+ )
900
908
  return content
901
909
 
902
910
 
@@ -1,13 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import operator
4
- from datetime import datetime
4
+ from datetime import datetime, timedelta
5
5
  from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Optional
6
6
 
7
7
  import strawberry
8
8
  from aioitertools.itertools import islice
9
9
  from openinference.semconv.trace import SpanAttributes
10
10
  from sqlalchemy import desc, distinct, func, or_, select
11
+ from sqlalchemy.dialects import postgresql, sqlite
11
12
  from sqlalchemy.sql.elements import ColumnElement
12
13
  from sqlalchemy.sql.expression import tuple_
13
14
  from strawberry import ID, UNSET, Private, lazy
@@ -17,6 +18,7 @@ from typing_extensions import assert_never
17
18
 
18
19
  from phoenix.datetime_utils import right_open_time_range
19
20
  from phoenix.db import models
21
+ from phoenix.db.helpers import SupportedSQLDialect
20
22
  from phoenix.server.api.context import Context
21
23
  from phoenix.server.api.input_types.ProjectSessionSort import (
22
24
  ProjectSessionColumn,
@@ -38,6 +40,7 @@ from phoenix.server.api.types.pagination import (
38
40
  from phoenix.server.api.types.ProjectSession import ProjectSession, to_gql_project_session
39
41
  from phoenix.server.api.types.SortDir import SortDir
40
42
  from phoenix.server.api.types.Span import Span
43
+ from phoenix.server.api.types.TimeSeries import TimeSeries, TimeSeriesDataPoint
41
44
  from phoenix.server.api.types.Trace import Trace
42
45
  from phoenix.server.api.types.ValidationResult import ValidationResult
43
46
  from phoenix.trace.dsl import SpanFilter
@@ -528,19 +531,46 @@ class Project(Node):
528
531
  return info.context.last_updated_at.get(self._table, self.project_rowid)
529
532
 
530
533
  @strawberry.field
531
- async def validate_span_filter_condition(self, condition: str) -> ValidationResult:
534
+ async def validate_span_filter_condition(
535
+ self,
536
+ info: Info[Context, None],
537
+ condition: str,
538
+ ) -> ValidationResult:
539
+ """Validates a span filter condition by attempting to compile it for both SQLite and PostgreSQL.
540
+
541
+ This method checks if the provided filter condition is syntactically valid and can be compiled
542
+ into SQL queries for both SQLite and PostgreSQL databases. It does not execute the query,
543
+ only validates its syntax. Any exception during compilation (syntax errors, invalid expressions,
544
+ etc.) will result in an invalid validation result.
545
+
546
+ Args:
547
+ condition (str): The span filter condition string to validate.
548
+
549
+ Returns:
550
+ ValidationResult: A result object containing:
551
+ - is_valid (bool): True if the condition is valid, False otherwise
552
+ - error_message (Optional[str]): Error message if validation fails, None if valid
553
+ """ # noqa: E501
532
554
  # This query is too expensive to run on every validation
533
555
  # valid_eval_names = await self.span_annotation_names()
534
556
  try:
535
- SpanFilter(
557
+ span_filter = SpanFilter(
536
558
  condition=condition,
537
559
  # valid_eval_names=valid_eval_names,
538
560
  )
561
+ stmt = span_filter(select(models.Span))
562
+ dialect = info.context.db.dialect
563
+ if dialect is SupportedSQLDialect.POSTGRESQL:
564
+ str(stmt.compile(dialect=sqlite.dialect())) # type: ignore[no-untyped-call]
565
+ elif dialect is SupportedSQLDialect.SQLITE:
566
+ str(stmt.compile(dialect=postgresql.dialect())) # type: ignore[no-untyped-call]
567
+ else:
568
+ assert_never(dialect)
539
569
  return ValidationResult(is_valid=True, error_message=None)
540
- except SyntaxError as e:
570
+ except Exception as e:
541
571
  return ValidationResult(
542
572
  is_valid=False,
543
- error_message=e.msg,
573
+ error_message=str(e),
544
574
  )
545
575
 
546
576
  @strawberry.field
@@ -610,6 +640,97 @@ class Project(Node):
610
640
  )
611
641
  return updated_at
612
642
 
643
+ @strawberry.field(
644
+ description="Hourly span count for the project.",
645
+ ) # type: ignore
646
+ async def span_count_time_series(
647
+ self,
648
+ info: Info[Context, None],
649
+ time_range: Optional[TimeRange] = UNSET,
650
+ ) -> SpanCountTimeSeries:
651
+ """Returns a time series of span counts grouped by hour for the project.
652
+
653
+ This field provides hourly aggregated span counts, which can be useful for
654
+ visualizing span activity over time. The data points represent the number
655
+ of spans that started in each hour.
656
+
657
+ Args:
658
+ info: The GraphQL info object containing context information.
659
+ time_range: Optional time range to filter the spans. If provided, only
660
+ spans that started within this range will be counted.
661
+
662
+ Returns:
663
+ A SpanCountTimeSeries object containing data points with timestamps
664
+ (rounded to the nearest hour) and corresponding span counts.
665
+
666
+ Notes:
667
+ - The timestamps are rounded down to the nearest hour.
668
+ - If a time range is provided, the start time is rounded down to the
669
+ nearest hour, and the end time is rounded up to the nearest hour.
670
+ - The SQL query is optimized for both PostgreSQL and SQLite databases.
671
+ """
672
+ # Determine the appropriate SQL function to truncate timestamps to hours
673
+ # based on the database dialect
674
+ if info.context.db.dialect is SupportedSQLDialect.POSTGRESQL:
675
+ # PostgreSQL uses date_trunc for timestamp truncation
676
+ hour = func.date_trunc("hour", models.Span.start_time)
677
+ elif info.context.db.dialect is SupportedSQLDialect.SQLITE:
678
+ # SQLite uses strftime for timestamp formatting
679
+ hour = func.strftime("%Y-%m-%dT%H:00:00.000+00:00", models.Span.start_time)
680
+ else:
681
+ assert_never(info.context.db.dialect)
682
+
683
+ # Build the base query to count spans grouped by hour
684
+ stmt = (
685
+ select(hour, func.count())
686
+ .join(models.Trace)
687
+ .where(models.Trace.project_rowid == self.project_rowid)
688
+ .group_by(hour)
689
+ .order_by(hour)
690
+ )
691
+
692
+ # Apply time range filtering if provided
693
+ if time_range:
694
+ if t := time_range.start:
695
+ # Round down to nearest hour for the start time
696
+ start = t.replace(minute=0, second=0, microsecond=0)
697
+ stmt = stmt.where(start <= models.Span.start_time)
698
+ if t := time_range.end:
699
+ # Round up to nearest hour for the end time
700
+ # If the time is already at the start of an hour, use it as is
701
+ if t.minute == 0 and t.second == 0 and t.microsecond == 0:
702
+ end = t
703
+ else:
704
+ # Otherwise, round up to the next hour
705
+ end = t.replace(minute=0, second=0, microsecond=0) + timedelta(hours=1)
706
+ stmt = stmt.where(models.Span.start_time < end)
707
+
708
+ # Execute the query and convert the results to a time series
709
+ async with info.context.db() as session:
710
+ data = await session.stream(stmt)
711
+ return SpanCountTimeSeries(
712
+ data=[
713
+ TimeSeriesDataPoint(
714
+ timestamp=_as_datetime(t),
715
+ value=v,
716
+ )
717
+ async for t, v in data
718
+ ]
719
+ )
720
+
721
+
722
+ @strawberry.type
723
+ class SpanCountTimeSeries(TimeSeries):
724
+ """A time series of span count"""
725
+
613
726
 
614
727
  INPUT_VALUE = SpanAttributes.INPUT_VALUE.split(".")
615
728
  OUTPUT_VALUE = SpanAttributes.OUTPUT_VALUE.split(".")
729
+
730
+
731
+ def _as_datetime(value: Any) -> datetime:
732
+ if isinstance(value, datetime):
733
+ return value
734
+ if isinstance(value, str):
735
+ return datetime.fromisoformat(value)
736
+ raise ValueError(f"Cannot convert {value} to datetime")
@@ -44,6 +44,8 @@ from phoenix.server.api.types.SpanAnnotation import SpanAnnotation, to_gql_span_
44
44
  from phoenix.server.api.types.SpanIOValue import SpanIOValue, truncate_value
45
45
  from phoenix.trace.attributes import get_attribute_value
46
46
 
47
+ from .TokenCountPromptDetails import TokenCountPromptDetails
48
+
47
49
  if TYPE_CHECKING:
48
50
  from phoenix.server.api.types.Project import Project
49
51
  from phoenix.server.api.types.Trace import Trace
@@ -351,6 +353,48 @@ class Span(Node):
351
353
  )
352
354
  return cast(Optional[int], value)
353
355
 
356
+ @strawberry.field
357
+ async def token_prompt_details(
358
+ self,
359
+ info: Info[Context, None],
360
+ ) -> TokenCountPromptDetails:
361
+ if self.db_span:
362
+ attributes = self.db_span.attributes
363
+ else:
364
+ attributes = await info.context.data_loaders.span_fields.load(
365
+ (self.span_rowid, models.Span.attributes),
366
+ )
367
+
368
+ cache_read: Optional[int] = None
369
+ raw_cache_read = get_attribute_value(
370
+ attributes=attributes,
371
+ key=LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ,
372
+ )
373
+ if isinstance(raw_cache_read, int):
374
+ cache_read = raw_cache_read
375
+
376
+ cache_write: Optional[int] = None
377
+ raw_cache_write = get_attribute_value(
378
+ attributes=attributes,
379
+ key=LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE,
380
+ )
381
+ if isinstance(raw_cache_write, int):
382
+ cache_write = raw_cache_write
383
+
384
+ audio: Optional[int] = None
385
+ raw_audio = get_attribute_value(
386
+ attributes=attributes,
387
+ key=LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO,
388
+ )
389
+ if isinstance(raw_audio, int):
390
+ audio = raw_audio
391
+
392
+ return TokenCountPromptDetails(
393
+ cache_read=cache_read,
394
+ cache_write=cache_write,
395
+ audio=audio,
396
+ )
397
+
354
398
  @strawberry.field
355
399
  async def input(
356
400
  self,
@@ -800,6 +844,11 @@ def _convert_metadata_to_string(metadata: Any) -> Optional[str]:
800
844
 
801
845
  INPUT_MIME_TYPE = SpanAttributes.INPUT_MIME_TYPE
802
846
  INPUT_VALUE = SpanAttributes.INPUT_VALUE
847
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO = SpanAttributes.LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO
848
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ = SpanAttributes.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ
849
+ LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE = (
850
+ SpanAttributes.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE
851
+ )
803
852
  METADATA = SpanAttributes.METADATA
804
853
  OUTPUT_MIME_TYPE = SpanAttributes.OUTPUT_MIME_TYPE
805
854
  OUTPUT_VALUE = SpanAttributes.OUTPUT_VALUE
@@ -0,0 +1,10 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+
5
+
6
+ @strawberry.type
7
+ class TokenCountPromptDetails:
8
+ cache_read: Optional[int]
9
+ cache_write: Optional[int]
10
+ audio: Optional[int]
@@ -0,0 +1,255 @@
1
+ import json
2
+ import os
3
+ import re
4
+ from collections import defaultdict
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ from typing import Any, Iterator, Optional, Union
8
+
9
+
10
+ @dataclass
11
+ class ModelTokenCost:
12
+ # Cost in USD
13
+ input: Optional[float] = None
14
+ output: Optional[float] = None
15
+ cache_write: Optional[float] = None
16
+ cache_read: Optional[float] = None
17
+ audio: Optional[float] = None
18
+
19
+
20
+ class RegexDict:
21
+ __slots__ = ("_entries",)
22
+
23
+ def __init__(self) -> None:
24
+ self._entries: list[tuple[re.Pattern[str], Any]] = []
25
+
26
+ def __setitem__(self, pattern: Union[str, re.Pattern[str]], value: Any) -> None:
27
+ if isinstance(pattern, str):
28
+ compiled = re.compile(pattern)
29
+ elif isinstance(pattern, re.Pattern):
30
+ compiled = pattern
31
+ else:
32
+ raise TypeError("RegexDict key must be a str or re.Pattern")
33
+
34
+ for idx, (existing_pat, _) in enumerate(self._entries):
35
+ if existing_pat.pattern == compiled.pattern and existing_pat.flags == compiled.flags:
36
+ self._entries[idx] = (compiled, value)
37
+ return
38
+ self._entries.append((compiled, value))
39
+
40
+ def __delitem__(self, pattern: Union[str, re.Pattern[str]]) -> None:
41
+ if isinstance(pattern, str):
42
+ target = pattern
43
+ elif isinstance(pattern, re.Pattern):
44
+ target = pattern.pattern
45
+ else:
46
+ raise TypeError("RegexDict key must be a str or re.Pattern")
47
+
48
+ for idx, (existing_pat, _) in enumerate(self._entries):
49
+ if existing_pat.pattern == target:
50
+ del self._entries[idx]
51
+ return
52
+ raise KeyError(pattern)
53
+
54
+ def __getitem__(self, key: str) -> Any:
55
+ for pattern, value in self._entries:
56
+ if pattern.fullmatch(key):
57
+ return value
58
+ raise KeyError(key)
59
+
60
+ def __contains__(self, key: str) -> bool:
61
+ try:
62
+ _ = self[key]
63
+ return True
64
+ except KeyError:
65
+ return False
66
+
67
+ def __iter__(self) -> Iterator[tuple[str, Any]]:
68
+ for pattern, value in self._entries:
69
+ yield pattern.pattern, value
70
+
71
+ def __len__(self) -> int:
72
+ return len(self._entries)
73
+
74
+
75
+ class ModelCostLookup:
76
+ __slots__ = ("_provider_model_map", "_model_map", "_overrides", "_cache", "_max_cache_size")
77
+
78
+ def __init__(self) -> None:
79
+ # Each provider maps to a *RegexDict* of (pattern -> cost).
80
+ self._provider_model_map: defaultdict[Optional[str], RegexDict] = defaultdict(RegexDict)
81
+ # Map from *pattern string* to a set of providers that have that pattern.
82
+ self._model_map: defaultdict[re.Pattern[str], set[Optional[str]]] = defaultdict(set)
83
+ # A prioritized list of cost overrides (later overrides have higher priority).
84
+ self._overrides: list[tuple[Optional[str], re.Pattern[str], ModelTokenCost]] = []
85
+ # Cache for computed costs keyed by (provider, model_name).
86
+ self._cache: dict[tuple[Optional[str], str], list[tuple[str, ModelTokenCost]]] = {}
87
+ self._max_cache_size = 100
88
+
89
+ def add_pattern(
90
+ self, provider: Optional[str], pattern: re.Pattern[str], cost: ModelTokenCost
91
+ ) -> None:
92
+ """Register a model pattern with its cost."""
93
+
94
+ assert isinstance(pattern, re.Pattern), "pattern must be a compiled regex"
95
+ self._provider_model_map[provider][pattern] = cost
96
+ self._model_map[pattern].add(provider)
97
+ self._cache.clear()
98
+
99
+ def remove_pattern(self, provider: Optional[str], pattern: re.Pattern[str]) -> None:
100
+ """Remove a previously-registered model pattern."""
101
+
102
+ assert isinstance(pattern, re.Pattern), "pattern must be a compiled regex"
103
+ if provider not in self._provider_model_map:
104
+ return
105
+ del self._provider_model_map[provider][pattern]
106
+ self._model_map[pattern].discard(provider)
107
+ if not self._provider_model_map[provider]:
108
+ del self._provider_model_map[provider]
109
+ if not self._model_map[pattern]:
110
+ del self._model_map[pattern]
111
+ self._cache.clear()
112
+
113
+ def get_cost(
114
+ self, provider: Optional[str], model_name: str
115
+ ) -> list[tuple[str, ModelTokenCost]]:
116
+ key = (provider, model_name)
117
+ if key in self._cache:
118
+ value = self._cache.pop(key)
119
+ self._cache[key] = value
120
+ return value
121
+
122
+ result = self._lookup_cost(provider, model_name)
123
+
124
+ if len(self._cache) >= self._max_cache_size:
125
+ self._cache.pop(next(iter(self._cache)))
126
+
127
+ self._cache[key] = result
128
+ return result
129
+
130
+ def has_model(self, provider: Optional[str], model_name: str) -> bool:
131
+ """Return ``True`` if a cost (either base or overridden) exists for the model."""
132
+
133
+ return self._contains(provider, model_name)
134
+
135
+ def pattern_count(self) -> int:
136
+ """Return the number of registered *base* patterns (overrides not counted)."""
137
+
138
+ return sum(len(regex_dict) for regex_dict in self._provider_model_map.values())
139
+
140
+ def _lookup_cost(
141
+ self, provider: Optional[str], model_name: str
142
+ ) -> list[tuple[str, ModelTokenCost]]:
143
+ assert isinstance(model_name, str), "Lookup key must be a str"
144
+ # 1) Provider-specific lookup
145
+ if provider is not None:
146
+ override_cost = self._lookup_override(provider, model_name)
147
+ if override_cost is not None:
148
+ return [(provider, override_cost)]
149
+
150
+ regex_dict = self._provider_model_map.get(provider)
151
+ if regex_dict is None:
152
+ raise KeyError(provider)
153
+ return [(provider, regex_dict[model_name])]
154
+
155
+ # 2) provider-agnostic lookup
156
+ provider_cost_map: dict[str, ModelTokenCost] = {}
157
+ for p, regex_dict in self._provider_model_map.items():
158
+ try:
159
+ provider_cost_map[p] = regex_dict[model_name] # type: ignore
160
+ except KeyError:
161
+ continue
162
+
163
+ for override_provider, override_pattern, override_cost in self._overrides:
164
+ if override_pattern.fullmatch(model_name):
165
+ if override_provider is None:
166
+ for p in list(provider_cost_map):
167
+ provider_cost_map[p] = override_cost
168
+ else:
169
+ provider_cost_map[override_provider] = override_cost
170
+
171
+ if not provider_cost_map:
172
+ raise KeyError(model_name)
173
+ return list(provider_cost_map.items())
174
+
175
+ def _contains(self, provider: Optional[str], model_name: str) -> bool:
176
+ if provider is None:
177
+ if any(pat.fullmatch(model_name) for _, pat, _ in self._overrides):
178
+ return True
179
+ return any(model_name in regex_dict for regex_dict in self._provider_model_map.values())
180
+
181
+ if self._lookup_override(provider, model_name) is not None:
182
+ return True
183
+
184
+ regex_dict = self._provider_model_map.get(provider)
185
+ if not regex_dict:
186
+ return False
187
+ return model_name in regex_dict
188
+
189
+ def add_override(
190
+ self, provider: Optional[str], pattern: re.Pattern[str], cost: ModelTokenCost
191
+ ) -> None:
192
+ """Register a *prioritized* cost override.
193
+
194
+ Overrides are evaluated in the order in which they are added (LIFO).
195
+ """
196
+
197
+ if not isinstance(pattern, re.Pattern):
198
+ raise TypeError("pattern must be a compiled regex")
199
+ self._overrides.append((provider, pattern, cost))
200
+ self._cache.clear()
201
+
202
+ def _lookup_override(
203
+ self, provider: Optional[str], model_name: str
204
+ ) -> Optional[ModelTokenCost]:
205
+ """Return the cost from the highest-priority override that matches, or *None*."""
206
+
207
+ for override_provider, override_pattern, override_cost in reversed(self._overrides):
208
+ provider_matches = override_provider is None or override_provider == provider
209
+ if provider_matches and override_pattern.fullmatch(model_name):
210
+ return override_cost
211
+ return None
212
+
213
+
214
+ def create_cost_table(
215
+ manifest_path: Optional[Union[str, "os.PathLike[str]"]] = None,
216
+ ) -> "ModelCostLookup":
217
+ if manifest_path is None:
218
+ manifest_path = Path(__file__).with_name("model_cost_manifest.json")
219
+
220
+ manifest_path = Path(manifest_path)
221
+
222
+ if not manifest_path.exists():
223
+ raise FileNotFoundError(f"Model cost manifest not found: {manifest_path}")
224
+
225
+ with manifest_path.open("r", encoding="utf-8") as fp:
226
+ try:
227
+ manifest_entries: list[dict[str, Any]] = json.load(fp)
228
+ except json.JSONDecodeError as exc:
229
+ raise ValueError(f"Failed to parse manifest JSON: {manifest_path}") from exc
230
+
231
+ lookup = ModelCostLookup()
232
+
233
+ for entry in manifest_entries:
234
+ provider: Optional[str] = entry.get("provider")
235
+
236
+ try:
237
+ pattern = re.compile(entry["regex"])
238
+ except re.error as exc:
239
+ raise ValueError(
240
+ f"Invalid regex in manifest for model {entry.get('model')}: {entry['regex']}"
241
+ ) from exc
242
+
243
+ cost = ModelTokenCost(
244
+ input=entry.get("input"),
245
+ output=entry.get("output"),
246
+ cache_write=entry.get("cache_write"),
247
+ cache_read=entry.get("cache_read"),
248
+ )
249
+
250
+ lookup.add_pattern(provider, pattern, cost)
251
+
252
+ return lookup
253
+
254
+
255
+ COST_TABLE = create_cost_table()