arize-phoenix 5.10.0__tar.gz → 5.12.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.
Files changed (332) hide show
  1. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/PKG-INFO +2 -1
  2. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/pyproject.toml +1 -0
  3. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/config.py +13 -0
  4. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/facilitator.py +3 -2
  5. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/helpers/playground_clients.py +64 -77
  6. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/helpers/playground_spans.py +6 -0
  7. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/chat_mutations.py +81 -36
  8. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/subscriptions.py +156 -58
  9. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/TemplateLanguage.py +1 -0
  10. arize_phoenix-5.12.0/src/phoenix/server/static/.vite/manifest.json +78 -0
  11. arize_phoenix-5.10.0/src/phoenix/server/static/assets/components-BXIz9ZO8.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/components-72cQL1d1.js +95 -95
  12. arize_phoenix-5.10.0/src/phoenix/server/static/assets/index-DTut7g1y.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/index-BowjltW-.js +1 -1
  13. arize_phoenix-5.10.0/src/phoenix/server/static/assets/pages-B8FpJuXu.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/pages-DFAkBAUh.js +339 -271
  14. arize_phoenix-5.10.0/src/phoenix/server/static/assets/vendor-BX8_Znqy.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/vendor-DexmGnha.js +150 -150
  15. arize_phoenix-5.10.0/src/phoenix/server/static/assets/vendor-arizeai-CtHir-Ua.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/vendor-arizeai--Q3ol330.js +28 -28
  16. arize_phoenix-5.10.0/src/phoenix/server/static/assets/vendor-codemirror-DLlGiguX.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/vendor-codemirror-B4bYvWa6.js +1 -1
  17. arize_phoenix-5.10.0/src/phoenix/server/static/assets/vendor-recharts-CJRple0d.js → arize_phoenix-5.12.0/src/phoenix/server/static/assets/vendor-recharts-B4ZzJhNh.js +1 -1
  18. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/span_evaluations.py +4 -3
  19. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/json.py +7 -1
  20. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/template_formatters.py +18 -0
  21. arize_phoenix-5.12.0/src/phoenix/version.py +1 -0
  22. arize_phoenix-5.10.0/src/phoenix/server/static/.vite/manifest.json +0 -78
  23. arize_phoenix-5.10.0/src/phoenix/version.py +0 -1
  24. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/.gitignore +0 -0
  25. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/IP_NOTICE +0 -0
  26. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/LICENSE +0 -0
  27. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/README.md +0 -0
  28. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/__init__.py +0 -0
  29. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/auth.py +0 -0
  30. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/core/__init__.py +0 -0
  31. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/core/embedding_dimension.py +0 -0
  32. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/core/model.py +0 -0
  33. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/core/model_schema.py +0 -0
  34. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  35. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/datetime_utils.py +0 -0
  36. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/README.md +0 -0
  37. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/__init__.py +0 -0
  38. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/alembic.ini +0 -0
  39. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/bulk_inserter.py +0 -0
  40. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/engines.py +0 -0
  41. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/enums.py +0 -0
  42. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/helpers.py +0 -0
  43. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/__init__.py +0 -0
  44. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/constants.py +0 -0
  45. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/dataset.py +0 -0
  46. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/document_annotation.py +0 -0
  47. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/evaluation.py +0 -0
  48. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/helpers.py +0 -0
  49. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/span.py +0 -0
  50. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/span_annotation.py +0 -0
  51. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/trace_annotation.py +0 -0
  52. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/insertion/types.py +0 -0
  53. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrate.py +0 -0
  54. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/__init__.py +0 -0
  55. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/env.py +0 -0
  56. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/script.py.mako +0 -0
  57. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  58. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +0 -0
  59. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/versions/cd164e83824f_users_and_tokens.py +0 -0
  60. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  61. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/db/models.py +0 -0
  62. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/exceptions.py +0 -0
  63. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/__init__.py +0 -0
  64. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  65. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/evaluators/base.py +0 -0
  66. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  67. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  68. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
  69. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/functions.py +0 -0
  70. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/tracing.py +0 -0
  71. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/types.py +0 -0
  72. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/experiments/utils.py +0 -0
  73. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/inferences/__init__.py +0 -0
  74. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/inferences/errors.py +0 -0
  75. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/inferences/fixtures.py +0 -0
  76. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/inferences/inferences.py +0 -0
  77. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/inferences/schema.py +0 -0
  78. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/inferences/validation.py +0 -0
  79. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/logging/__init__.py +0 -0
  80. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/logging/_config.py +0 -0
  81. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/logging/_filter.py +0 -0
  82. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/logging/_formatter.py +0 -0
  83. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/README.md +0 -0
  84. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/__init__.py +0 -0
  85. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/binning.py +0 -0
  86. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/metrics.py +0 -0
  87. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/mixins.py +0 -0
  88. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  89. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/timeseries.py +0 -0
  90. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/metrics/wrappers.py +0 -0
  91. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/pointcloud/__init__.py +0 -0
  92. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/pointcloud/clustering.py +0 -0
  93. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  94. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/pointcloud/projectors.py +0 -0
  95. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  96. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/py.typed +0 -0
  97. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/__init__.py +0 -0
  98. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/README.md +0 -0
  99. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/__init__.py +0 -0
  100. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/auth.py +0 -0
  101. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/context.py +0 -0
  102. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/__init__.py +0 -0
  103. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  104. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  105. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  106. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  107. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  108. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  109. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  110. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  111. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  112. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  113. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  114. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/experiment_run_annotations.py +0 -0
  115. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  116. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  117. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  118. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  119. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  120. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  121. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  122. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  123. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  124. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  125. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  126. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/trace_row_ids.py +0 -0
  127. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/user_roles.py +0 -0
  128. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/dataloaders/users.py +0 -0
  129. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/exceptions.py +0 -0
  130. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
  131. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  132. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/helpers/playground_registry.py +0 -0
  133. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  134. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  135. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/ChatCompletionInput.py +0 -0
  136. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/ChatCompletionMessageInput.py +0 -0
  137. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  138. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  139. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  140. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  141. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  142. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  143. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  144. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  145. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  146. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  147. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  148. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  149. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  150. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  151. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  152. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  153. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/GenerativeModelInput.py +0 -0
  154. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  155. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/InvocationParameters.py +0 -0
  156. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  157. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  158. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  159. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  160. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  161. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  162. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/TemplateOptions.py +0 -0
  163. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  164. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  165. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/UserRoleInput.py +0 -0
  166. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
  167. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/interceptor.py +0 -0
  168. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/__init__.py +0 -0
  169. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/api_key_mutations.py +0 -0
  170. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
  171. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
  172. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  173. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
  174. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +0 -0
  175. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +0 -0
  176. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/mutations/user_mutations.py +0 -0
  177. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/openapi/__init__.py +0 -0
  178. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/openapi/main.py +0 -0
  179. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/openapi/schema.py +0 -0
  180. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/queries.py +0 -0
  181. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/__init__.py +0 -0
  182. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/auth.py +0 -0
  183. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/embeddings.py +0 -0
  184. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/oauth2.py +0 -0
  185. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/utils.py +0 -0
  186. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/__init__.py +0 -0
  187. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/datasets.py +0 -0
  188. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  189. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -0
  190. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -0
  191. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/experiments.py +0 -0
  192. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/pydantic_compat.py +0 -0
  193. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/spans.py +0 -0
  194. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/traces.py +0 -0
  195. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  196. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/schema.py +0 -0
  197. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Annotation.py +0 -0
  198. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  199. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  200. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ApiKey.py +0 -0
  201. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/AuthMethod.py +0 -0
  202. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ChatCompletionMessageRole.py +0 -0
  203. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +0 -0
  204. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  205. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  206. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  207. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  208. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  209. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  210. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  211. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  212. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  213. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  214. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  215. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  216. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  217. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  218. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  219. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  220. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  221. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
  222. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  223. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Event.py +0 -0
  224. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  225. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  226. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Experiment.py +0 -0
  227. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  228. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  229. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
  230. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  231. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  232. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  233. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/GenerativeModel.py +0 -0
  234. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/GenerativeProvider.py +0 -0
  235. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Inferences.py +0 -0
  236. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  237. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  238. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  239. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Model.py +0 -0
  240. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  241. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  242. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Project.py +0 -0
  243. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  244. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  245. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  246. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Segments.py +0 -0
  247. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  248. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Span.py +0 -0
  249. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  250. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/SystemApiKey.py +0 -0
  251. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  252. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/Trace.py +0 -0
  253. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  254. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  255. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/User.py +0 -0
  256. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/UserApiKey.py +0 -0
  257. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/UserRole.py +0 -0
  258. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  259. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  260. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/__init__.py +0 -0
  261. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/node.py +0 -0
  262. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/types/pagination.py +0 -0
  263. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/api/utils.py +0 -0
  264. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/app.py +0 -0
  265. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/bearer_auth.py +0 -0
  266. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/dml_event.py +0 -0
  267. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/dml_event_handler.py +0 -0
  268. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/email/__init__.py +0 -0
  269. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/email/sender.py +0 -0
  270. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/email/templates/__init__.py +0 -0
  271. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/email/templates/password_reset.html +0 -0
  272. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/email/types.py +0 -0
  273. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/grpc_server.py +0 -0
  274. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/jwt_store.py +0 -0
  275. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/main.py +0 -0
  276. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/oauth2.py +0 -0
  277. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/openapi/__init__.py +0 -0
  278. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/prometheus.py +0 -0
  279. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/rate_limiters.py +0 -0
  280. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  281. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  282. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  283. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  284. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  285. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  286. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  287. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  288. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/assets/vendor-DxkFTwjz.css +0 -0
  289. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/assets/vendor-three-DwGkEfCM.js +0 -0
  290. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/favicon.ico +0 -0
  291. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/static/modernizr.js +0 -0
  292. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/telemetry.py +0 -0
  293. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/templates/__init__.py +0 -0
  294. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/templates/index.html +0 -0
  295. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/thread_server.py +0 -0
  296. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/server/types.py +0 -0
  297. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/services.py +0 -0
  298. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/session/__init__.py +0 -0
  299. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/session/client.py +0 -0
  300. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/session/data_extractor.py +0 -0
  301. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/session/evaluation.py +0 -0
  302. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/session/session.py +0 -0
  303. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/settings.py +0 -0
  304. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/__init__.py +0 -0
  305. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/attributes.py +0 -0
  306. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/dsl/README.md +0 -0
  307. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  308. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/dsl/filter.py +0 -0
  309. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  310. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/dsl/query.py +0 -0
  311. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/errors.py +0 -0
  312. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  313. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/exporter.py +0 -0
  314. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/fixtures.py +0 -0
  315. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/otel.py +0 -0
  316. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/projects.py +0 -0
  317. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/schemas.py +0 -0
  318. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  319. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  320. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/trace_dataset.py +0 -0
  321. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/utils.py +0 -0
  322. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/v1/__init__.py +0 -0
  323. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  324. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  325. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/__init__.py +0 -0
  326. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/client.py +0 -0
  327. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/deprecation.py +0 -0
  328. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/error_handling.py +0 -0
  329. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/logging.py +0 -0
  330. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/project.py +0 -0
  331. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/re.py +0 -0
  332. {arize_phoenix-5.10.0 → arize_phoenix-5.12.0}/src/phoenix/utilities/span_store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arize-phoenix
3
- Version: 5.10.0
3
+ Version: 5.12.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
@@ -53,6 +53,7 @@ Requires-Dist: wrapt
53
53
  Provides-Extra: container
54
54
  Requires-Dist: anthropic; extra == 'container'
55
55
  Requires-Dist: fast-hdbscan>=0.2.0; extra == 'container'
56
+ Requires-Dist: google-generativeai; extra == 'container'
56
57
  Requires-Dist: numba>=0.60.0; extra == 'container'
57
58
  Requires-Dist: openai>=1.0.0; extra == 'container'
58
59
  Requires-Dist: opentelemetry-exporter-otlp; extra == 'container'
@@ -121,6 +121,7 @@ pg = [
121
121
  ]
122
122
  container = [
123
123
  "anthropic",
124
+ "google-generativeai",
124
125
  "prometheus-client",
125
126
  "openai>=1.0.0",
126
127
  "opentelemetry-sdk",
@@ -97,6 +97,13 @@ ENV_PHOENIX_SERVER_INSTRUMENTATION_OTLP_TRACE_COLLECTOR_GRPC_ENDPOINT = (
97
97
  ENV_PHOENIX_ENABLE_AUTH = "PHOENIX_ENABLE_AUTH"
98
98
  ENV_PHOENIX_DISABLE_RATE_LIMIT = "PHOENIX_DISABLE_RATE_LIMIT"
99
99
  ENV_PHOENIX_SECRET = "PHOENIX_SECRET"
100
+ ENV_PHOENIX_DEFAULT_ADMIN_INITIAL_PASSWORD = "PHOENIX_DEFAULT_ADMIN_INITIAL_PASSWORD"
101
+ """
102
+ The initial password for the default admin account, which defaults to ‘admin’ if not
103
+ explicitly set. Note that changing this value will have no effect if the default admin
104
+ record already exists in the database. In such cases, the default admin password must
105
+ be updated manually in the application.
106
+ """
100
107
  ENV_PHOENIX_API_KEY = "PHOENIX_API_KEY"
101
108
  ENV_PHOENIX_USE_SECURE_COOKIES = "PHOENIX_USE_SECURE_COOKIES"
102
109
  ENV_PHOENIX_ACCESS_TOKEN_EXPIRY_MINUTES = "PHOENIX_ACCESS_TOKEN_EXPIRY_MINUTES"
@@ -274,6 +281,12 @@ def get_env_phoenix_secret() -> Optional[str]:
274
281
  return phoenix_secret
275
282
 
276
283
 
284
+ def get_env_default_admin_initial_password() -> str:
285
+ from phoenix.auth import DEFAULT_ADMIN_PASSWORD
286
+
287
+ return os.environ.get(ENV_PHOENIX_DEFAULT_ADMIN_INITIAL_PASSWORD) or DEFAULT_ADMIN_PASSWORD
288
+
289
+
277
290
  def get_env_phoenix_use_secure_cookies() -> bool:
278
291
  return _bool_val(ENV_PHOENIX_USE_SECURE_COOKIES, False)
279
292
 
@@ -13,13 +13,13 @@ from sqlalchemy.ext.asyncio import AsyncSession
13
13
 
14
14
  from phoenix.auth import (
15
15
  DEFAULT_ADMIN_EMAIL,
16
- DEFAULT_ADMIN_PASSWORD,
17
16
  DEFAULT_ADMIN_USERNAME,
18
17
  DEFAULT_SECRET_LENGTH,
19
18
  DEFAULT_SYSTEM_EMAIL,
20
19
  DEFAULT_SYSTEM_USERNAME,
21
20
  compute_password_hash,
22
21
  )
22
+ from phoenix.config import get_env_default_admin_initial_password
23
23
  from phoenix.db import models
24
24
  from phoenix.db.enums import COLUMN_ENUMS, UserRole
25
25
  from phoenix.server.types import DbSessionFactory
@@ -97,7 +97,8 @@ async def _ensure_user_roles(session: AsyncSession) -> None:
97
97
  admin_role_id := role_ids.get(admin_role)
98
98
  ) is not None:
99
99
  salt = secrets.token_bytes(DEFAULT_SECRET_LENGTH)
100
- compute = partial(compute_password_hash, password=DEFAULT_ADMIN_PASSWORD, salt=salt)
100
+ password = get_env_default_admin_initial_password()
101
+ compute = partial(compute_password_hash, password=password, salt=salt)
101
102
  loop = asyncio.get_running_loop()
102
103
  hash_ = await loop.run_in_executor(None, compute)
103
104
  admin_user = models.User(
@@ -2,6 +2,7 @@ import asyncio
2
2
  import importlib.util
3
3
  import inspect
4
4
  import json
5
+ import os
5
6
  import time
6
7
  from abc import ABC, abstractmethod
7
8
  from collections.abc import AsyncIterator, Callable, Iterator
@@ -25,6 +26,7 @@ from phoenix.evals.models.rate_limiters import (
25
26
  RateLimiter,
26
27
  RateLimitError,
27
28
  )
29
+ from phoenix.server.api.exceptions import BadRequest
28
30
  from phoenix.server.api.helpers.playground_registry import PROVIDER_DEFAULT, register_llm_client
29
31
  from phoenix.server.api.input_types.GenerativeModelInput import GenerativeModelInput
30
32
  from phoenix.server.api.input_types.InvocationParameters import (
@@ -99,9 +101,9 @@ class PlaygroundRateLimiter(RateLimiter, KeyedSingleton):
99
101
  super().__init__(
100
102
  rate_limit_error=rate_limit_error,
101
103
  max_rate_limit_retries=3,
102
- initial_per_second_request_rate=2.0,
103
- maximum_per_second_request_rate=10.0,
104
- enforcement_window_minutes=1,
104
+ initial_per_second_request_rate=1.0,
105
+ maximum_per_second_request_rate=3.0,
106
+ enforcement_window_minutes=0.05,
105
107
  rate_reduction_factor=0.5,
106
108
  rate_increase_factor=0.01,
107
109
  cooldown_seconds=5,
@@ -128,10 +130,11 @@ class PlaygroundRateLimiter(RateLimiter, KeyedSingleton):
128
130
  self._rate_limit_handling.set() # Set the event as a failsafe
129
131
  await self._throttler.async_wait_until_ready()
130
132
  request_start_time = time.time()
131
- if inspect.iscoroutinefunction(fn):
132
- return await fn(*args, **kwargs) # type: ignore
133
+ maybe_coroutine = fn(*args, **kwargs)
134
+ if inspect.isawaitable(maybe_coroutine):
135
+ return await maybe_coroutine # type: ignore[no-any-return]
133
136
  else:
134
- return fn(*args, **kwargs)
137
+ return maybe_coroutine
135
138
  except self._rate_limit_error:
136
139
  async with self._rate_limit_handling_lock:
137
140
  self._rate_limit_handling.clear() # prevent new requests from starting
@@ -141,10 +144,11 @@ class PlaygroundRateLimiter(RateLimiter, KeyedSingleton):
141
144
  try:
142
145
  request_start_time = time.time()
143
146
  await self._throttler.async_wait_until_ready()
144
- if inspect.iscoroutinefunction(fn):
145
- return await fn(*args, **kwargs) # type: ignore
147
+ maybe_coroutine = fn(*args, **kwargs)
148
+ if inspect.isawaitable(maybe_coroutine):
149
+ return await maybe_coroutine # type: ignore[no-any-return]
146
150
  else:
147
- return fn(*args, **kwargs)
151
+ return maybe_coroutine
148
152
  except self._rate_limit_error:
149
153
  self._throttler.on_rate_limit_error(
150
154
  request_start_time, verbose=self._verbose
@@ -258,6 +262,10 @@ class OpenAIStreamingClient(PlaygroundStreamingClient):
258
262
  from openai import AsyncOpenAI
259
263
  from openai import RateLimitError as OpenAIRateLimitError
260
264
 
265
+ # todo: check if custom base url is set before raising error to allow
266
+ # for custom endpoints that don't require an API key
267
+ if not (api_key := api_key or os.environ.get("OPENAI_API_KEY")):
268
+ raise BadRequest("An API key is required for OpenAI models")
261
269
  super().__init__(model=model, api_key=api_key)
262
270
  self._attributes[LLM_PROVIDER] = OpenInferenceLLMProviderValues.OPENAI.value
263
271
  self._attributes[LLM_SYSTEM] = OpenInferenceLLMSystemValues.OPENAI.value
@@ -288,12 +296,14 @@ class OpenAIStreamingClient(PlaygroundStreamingClient):
288
296
  BoundedFloatInvocationParameter(
289
297
  invocation_name="frequency_penalty",
290
298
  label="Frequency Penalty",
299
+ default_value=0.0,
291
300
  min_value=-2.0,
292
301
  max_value=2.0,
293
302
  ),
294
303
  BoundedFloatInvocationParameter(
295
304
  invocation_name="presence_penalty",
296
305
  label="Presence Penalty",
306
+ default_value=0.0,
297
307
  min_value=-2.0,
298
308
  max_value=2.0,
299
309
  ),
@@ -306,12 +316,14 @@ class OpenAIStreamingClient(PlaygroundStreamingClient):
306
316
  invocation_name="top_p",
307
317
  canonical_name=CanonicalParameterName.TOP_P,
308
318
  label="Top P",
319
+ default_value=1.0,
309
320
  min_value=0.0,
310
321
  max_value=1.0,
311
322
  ),
312
323
  IntInvocationParameter(
313
324
  invocation_name="seed",
314
325
  canonical_name=CanonicalParameterName.RANDOM_SEED,
326
+ default_value=0,
315
327
  label="Seed",
316
328
  ),
317
329
  JSONInvocationParameter(
@@ -338,10 +350,14 @@ class OpenAIStreamingClient(PlaygroundStreamingClient):
338
350
  from openai.types.chat import ChatCompletionStreamOptionsParam
339
351
 
340
352
  # Convert standard messages to OpenAI messages
341
- openai_messages = [self.to_openai_chat_completion_param(*message) for message in messages]
353
+ openai_messages = []
354
+ for message in messages:
355
+ openai_message = self.to_openai_chat_completion_param(*message)
356
+ if openai_message is not None:
357
+ openai_messages.append(openai_message)
342
358
  tool_call_ids: dict[int, str] = {}
343
359
  token_usage: Optional["CompletionUsage"] = None
344
- throttled_create = self.rate_limiter.alimit(self.client.chat.completions.create)
360
+ throttled_create = self.rate_limiter._alimit(self.client.chat.completions.create)
345
361
  async for chunk in await throttled_create(
346
362
  messages=openai_messages,
347
363
  model=self.model_name,
@@ -388,7 +404,7 @@ class OpenAIStreamingClient(PlaygroundStreamingClient):
388
404
  content: JSONScalarType,
389
405
  tool_call_id: Optional[str] = None,
390
406
  tool_calls: Optional[list[JSONScalarType]] = None,
391
- ) -> "ChatCompletionMessageParam":
407
+ ) -> Optional["ChatCompletionMessageParam"]:
392
408
  from openai.types.chat import (
393
409
  ChatCompletionAssistantMessageParam,
394
410
  ChatCompletionSystemMessageParam,
@@ -480,6 +496,7 @@ class OpenAIO1StreamingClient(OpenAIStreamingClient):
480
496
  invocation_name="seed",
481
497
  canonical_name=CanonicalParameterName.RANDOM_SEED,
482
498
  label="Seed",
499
+ default_value=0,
483
500
  ),
484
501
  JSONInvocationParameter(
485
502
  invocation_name="tool_choice",
@@ -488,65 +505,7 @@ class OpenAIO1StreamingClient(OpenAIStreamingClient):
488
505
  ),
489
506
  ]
490
507
 
491
- async def chat_completion_create(
492
- self,
493
- messages: list[
494
- tuple[ChatCompletionMessageRole, str, Optional[str], Optional[list[JSONScalarType]]]
495
- ],
496
- tools: list[JSONScalarType],
497
- **invocation_parameters: Any,
498
- ) -> AsyncIterator[ChatCompletionChunk]:
499
- from openai import NOT_GIVEN
500
-
501
- # Convert standard messages to OpenAI messages
502
- unfiltered_openai_messages = [
503
- self.to_openai_o1_chat_completion_param(*message) for message in messages
504
- ]
505
-
506
- # filter out unsupported messages
507
- openai_messages: list[ChatCompletionMessageParam] = [
508
- message for message in unfiltered_openai_messages if message is not None
509
- ]
510
-
511
- tool_call_ids: dict[int, str] = {}
512
-
513
- throttled_create = self.rate_limiter.alimit(self.client.chat.completions.create)
514
- response = await throttled_create(
515
- messages=openai_messages,
516
- model=self.model_name,
517
- tools=tools or NOT_GIVEN,
518
- **invocation_parameters,
519
- )
520
-
521
- choice = response.choices[0]
522
- message = choice.message
523
- content = message.content
524
-
525
- text_chunk = TextChunk(content=content)
526
- yield text_chunk
527
-
528
- if (tool_calls := message.tool_calls) is not None:
529
- for tool_call_index, tool_call in enumerate(tool_calls):
530
- tool_call_id = (
531
- tool_call.id
532
- if tool_call.id is not None
533
- else tool_call_ids.get(tool_call_index, f"tool_call_{tool_call_index}")
534
- )
535
- tool_call_ids[tool_call_index] = tool_call_id
536
- if (function := tool_call.function) is not None:
537
- tool_call_chunk = ToolCallChunk(
538
- id=tool_call_id,
539
- function=FunctionCallChunk(
540
- name=function.name or "",
541
- arguments=function.arguments or "",
542
- ),
543
- )
544
- yield tool_call_chunk
545
-
546
- if (usage := response.usage) is not None:
547
- self._attributes.update(dict(self._llm_token_counts(usage)))
548
-
549
- def to_openai_o1_chat_completion_param(
508
+ def to_openai_chat_completion_param(
550
509
  self,
551
510
  role: ChatCompletionMessageRole,
552
511
  content: JSONScalarType,
@@ -618,12 +577,14 @@ class AzureOpenAIStreamingClient(OpenAIStreamingClient):
618
577
  super().__init__(model=model, api_key=api_key)
619
578
  self._attributes[LLM_PROVIDER] = OpenInferenceLLMProviderValues.AZURE.value
620
579
  self._attributes[LLM_SYSTEM] = OpenInferenceLLMSystemValues.OPENAI.value
621
- if model.endpoint is None or model.api_version is None:
622
- raise ValueError("endpoint and api_version are required for Azure OpenAI models")
580
+ if not (endpoint := model.endpoint or os.environ.get("AZURE_OPENAI_ENDPOINT")):
581
+ raise BadRequest("An Azure endpoint is required for Azure OpenAI models")
582
+ if not (api_version := model.api_version or os.environ.get("OPENAI_API_VERSION")):
583
+ raise BadRequest("An OpenAI API version is required for Azure OpenAI models")
623
584
  self.client = AsyncAzureOpenAI(
624
585
  api_key=api_key,
625
- azure_endpoint=model.endpoint,
626
- api_version=model.api_version,
586
+ azure_endpoint=endpoint,
587
+ api_version=api_version,
627
588
  )
628
589
 
629
590
 
@@ -631,8 +592,12 @@ class AzureOpenAIStreamingClient(OpenAIStreamingClient):
631
592
  provider_key=GenerativeProviderKey.ANTHROPIC,
632
593
  model_names=[
633
594
  PROVIDER_DEFAULT,
595
+ "claude-3-5-sonnet-latest",
596
+ "claude-3-5-haiku-latest",
597
+ "claude-3-5-sonnet-20241022",
598
+ "claude-3-5-haiku-20241022",
634
599
  "claude-3-5-sonnet-20240620",
635
- "claude-3-opus-20240229",
600
+ "claude-3-opus-latest",
636
601
  "claude-3-sonnet-20240229",
637
602
  "claude-3-haiku-20240307",
638
603
  ],
@@ -648,6 +613,8 @@ class AnthropicStreamingClient(PlaygroundStreamingClient):
648
613
  super().__init__(model=model, api_key=api_key)
649
614
  self._attributes[LLM_PROVIDER] = OpenInferenceLLMProviderValues.ANTHROPIC.value
650
615
  self._attributes[LLM_SYSTEM] = OpenInferenceLLMSystemValues.ANTHROPIC.value
616
+ if not (api_key := api_key or os.environ.get("ANTHROPIC_API_KEY")):
617
+ raise BadRequest("An API key is required for Anthropic models")
651
618
  self.client = anthropic.AsyncAnthropic(api_key=api_key)
652
619
  self.model_name = model.name
653
620
  self.rate_limiter = PlaygroundRateLimiter(model.provider_key, anthropic.RateLimitError)
@@ -663,12 +630,14 @@ class AnthropicStreamingClient(PlaygroundStreamingClient):
663
630
  invocation_name="max_tokens",
664
631
  canonical_name=CanonicalParameterName.MAX_COMPLETION_TOKENS,
665
632
  label="Max Tokens",
633
+ default_value=1024,
666
634
  required=True,
667
635
  ),
668
636
  BoundedFloatInvocationParameter(
669
637
  invocation_name="temperature",
670
638
  canonical_name=CanonicalParameterName.TEMPERATURE,
671
639
  label="Temperature",
640
+ default_value=0.0,
672
641
  min_value=0.0,
673
642
  max_value=1.0,
674
643
  ),
@@ -681,6 +650,7 @@ class AnthropicStreamingClient(PlaygroundStreamingClient):
681
650
  invocation_name="top_p",
682
651
  canonical_name=CanonicalParameterName.TOP_P,
683
652
  label="Top P",
653
+ default_value=1.0,
684
654
  min_value=0.0,
685
655
  max_value=1.0,
686
656
  ),
@@ -707,7 +677,6 @@ class AnthropicStreamingClient(PlaygroundStreamingClient):
707
677
  "messages": anthropic_messages,
708
678
  "model": self.model_name,
709
679
  "system": system_prompt,
710
- "max_tokens": 1024,
711
680
  "tools": tools,
712
681
  **invocation_parameters,
713
682
  }
@@ -820,6 +789,12 @@ class GeminiStreamingClient(PlaygroundStreamingClient):
820
789
  super().__init__(model=model, api_key=api_key)
821
790
  self._attributes[LLM_PROVIDER] = OpenInferenceLLMProviderValues.GOOGLE.value
822
791
  self._attributes[LLM_SYSTEM] = OpenInferenceLLMSystemValues.VERTEXAI.value
792
+ if not (
793
+ api_key := api_key
794
+ or os.environ.get("GEMINI_API_KEY")
795
+ or os.environ.get("GOOGLE_API_KEY")
796
+ ):
797
+ raise BadRequest("An API key is required for Gemini models")
823
798
  google_genai.configure(api_key=api_key)
824
799
  self.model_name = model.name
825
800
 
@@ -851,21 +826,25 @@ class GeminiStreamingClient(PlaygroundStreamingClient):
851
826
  FloatInvocationParameter(
852
827
  invocation_name="presence_penalty",
853
828
  label="Presence Penalty",
829
+ default_value=0.0,
854
830
  ),
855
831
  FloatInvocationParameter(
856
832
  invocation_name="frequency_penalty",
857
833
  label="Frequency Penalty",
834
+ default_value=0.0,
858
835
  ),
859
836
  BoundedFloatInvocationParameter(
860
837
  invocation_name="top_p",
861
838
  canonical_name=CanonicalParameterName.TOP_P,
862
839
  label="Top P",
840
+ default_value=1.0,
863
841
  min_value=0.0,
864
842
  max_value=1.0,
865
843
  ),
866
844
  BoundedFloatInvocationParameter(
867
845
  invocation_name="top_k",
868
846
  label="Top K",
847
+ default_value=1.0,
869
848
  min_value=0.0,
870
849
  max_value=1.0,
871
850
  ),
@@ -873,6 +852,7 @@ class GeminiStreamingClient(PlaygroundStreamingClient):
873
852
  invocation_name="seed",
874
853
  canonical_name=CanonicalParameterName.RANDOM_SEED,
875
854
  label="Seed",
855
+ default_value=0,
876
856
  ),
877
857
  ]
878
858
 
@@ -907,6 +887,13 @@ class GeminiStreamingClient(PlaygroundStreamingClient):
907
887
  chat = client.start_chat(history=gemini_message_history)
908
888
  stream = await chat.send_message_async(**gemini_params)
909
889
  async for event in stream:
890
+ self._attributes.update(
891
+ {
892
+ LLM_TOKEN_COUNT_PROMPT: event.usage_metadata.prompt_token_count,
893
+ LLM_TOKEN_COUNT_COMPLETION: event.usage_metadata.candidates_token_count,
894
+ LLM_TOKEN_COUNT_TOTAL: event.usage_metadata.total_token_count,
895
+ }
896
+ )
910
897
  yield TextChunk(content=event.text)
911
898
 
912
899
  def _build_gemini_messages(
@@ -379,6 +379,11 @@ def _llm_output_messages(
379
379
  if content := "".join(chunk.content for chunk in text_chunks):
380
380
  yield f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_CONTENT}", content
381
381
  for tool_call_index, (_tool_call_id, tool_call_chunks_) in enumerate(tool_call_chunks.items()):
382
+ if _tool_call_id:
383
+ yield (
384
+ f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_ID}",
385
+ _tool_call_id,
386
+ )
382
387
  if tool_call_chunks_ and (name := tool_call_chunks_[0].function.name):
383
388
  yield (
384
389
  f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_NAME}",
@@ -441,6 +446,7 @@ MESSAGE_CONTENT = MessageAttributes.MESSAGE_CONTENT
441
446
  MESSAGE_ROLE = MessageAttributes.MESSAGE_ROLE
442
447
  MESSAGE_TOOL_CALLS = MessageAttributes.MESSAGE_TOOL_CALLS
443
448
 
449
+ TOOL_CALL_ID = ToolCallAttributes.TOOL_CALL_ID
444
450
  TOOL_CALL_FUNCTION_NAME = ToolCallAttributes.TOOL_CALL_FUNCTION_NAME
445
451
  TOOL_CALL_FUNCTION_ARGUMENTS_JSON = ToolCallAttributes.TOOL_CALL_FUNCTION_ARGUMENTS_JSON
446
452
  TOOL_CALL_ID = ToolCallAttributes.TOOL_CALL_ID
@@ -1,9 +1,9 @@
1
1
  import asyncio
2
2
  from dataclasses import asdict, field
3
3
  from datetime import datetime, timezone
4
- from itertools import chain
4
+ from itertools import chain, islice
5
5
  from traceback import format_exc
6
- from typing import Any, Iterable, Iterator, List, Optional, Union
6
+ from typing import Any, Iterable, Iterator, List, Optional, TypeVar, Union
7
7
 
8
8
  import strawberry
9
9
  from openinference.instrumentation import safe_json_dumps
@@ -25,8 +25,9 @@ from typing_extensions import assert_never
25
25
  from phoenix.datetime_utils import local_now, normalize_datetime
26
26
  from phoenix.db import models
27
27
  from phoenix.db.helpers import get_dataset_example_revisions
28
+ from phoenix.server.api.auth import IsNotReadOnly
28
29
  from phoenix.server.api.context import Context
29
- from phoenix.server.api.exceptions import BadRequest, NotFound
30
+ from phoenix.server.api.exceptions import BadRequest, CustomGraphQLError, NotFound
30
31
  from phoenix.server.api.helpers.playground_clients import (
31
32
  PlaygroundStreamingClient,
32
33
  initialize_playground_clients,
@@ -67,6 +68,7 @@ from phoenix.utilities.json import jsonify
67
68
  from phoenix.utilities.template_formatters import (
68
69
  FStringTemplateFormatter,
69
70
  MustacheTemplateFormatter,
71
+ NoOpFormatter,
70
72
  TemplateFormatter,
71
73
  )
72
74
 
@@ -117,7 +119,7 @@ class ChatCompletionOverDatasetMutationPayload:
117
119
 
118
120
  @strawberry.type
119
121
  class ChatCompletionMutationMixin:
120
- @strawberry.mutation
122
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
121
123
  @classmethod
122
124
  async def chat_completion_over_dataset(
123
125
  cls,
@@ -127,11 +129,19 @@ class ChatCompletionMutationMixin:
127
129
  provider_key = input.model.provider_key
128
130
  llm_client_class = PLAYGROUND_CLIENT_REGISTRY.get_client(provider_key, input.model.name)
129
131
  if llm_client_class is None:
130
- raise BadRequest(f"No LLM client registered for provider '{provider_key}'")
131
- llm_client = llm_client_class(
132
- model=input.model,
133
- api_key=input.api_key,
134
- )
132
+ raise BadRequest(f"Unknown LLM provider: '{provider_key.value}'")
133
+ try:
134
+ llm_client = llm_client_class(
135
+ model=input.model,
136
+ api_key=input.api_key,
137
+ )
138
+ except CustomGraphQLError:
139
+ raise
140
+ except Exception as error:
141
+ raise BadRequest(
142
+ f"Failed to connect to LLM API for {provider_key.value} {input.model.name}: "
143
+ f"{str(error)}"
144
+ )
135
145
  dataset_id = from_global_id_with_expected_type(input.dataset_id, Dataset.__name__)
136
146
  dataset_version_id = (
137
147
  from_global_id_with_expected_type(
@@ -158,7 +168,9 @@ class ChatCompletionMutationMixin:
158
168
  revisions = [
159
169
  revision
160
170
  async for revision in await session.stream_scalars(
161
- get_dataset_example_revisions(resolved_version_id)
171
+ get_dataset_example_revisions(resolved_version_id).order_by(
172
+ models.DatasetExampleRevision.id
173
+ )
162
174
  )
163
175
  ]
164
176
  if not revisions:
@@ -181,28 +193,32 @@ class ChatCompletionMutationMixin:
181
193
  session.add(experiment)
182
194
  await session.flush()
183
195
 
196
+ results = []
197
+ batch_size = 3
184
198
  start_time = datetime.now(timezone.utc)
185
- results = await asyncio.gather(
186
- *(
187
- cls._chat_completion(
188
- info,
189
- llm_client,
190
- ChatCompletionInput(
191
- model=input.model,
192
- api_key=input.api_key,
193
- messages=input.messages,
194
- tools=input.tools,
195
- invocation_parameters=input.invocation_parameters,
196
- template=TemplateOptions(
197
- language=input.template_language,
198
- variables=revision.input,
199
+ for batch in _get_batches(revisions, batch_size):
200
+ batch_results = await asyncio.gather(
201
+ *(
202
+ cls._chat_completion(
203
+ info,
204
+ llm_client,
205
+ ChatCompletionInput(
206
+ model=input.model,
207
+ api_key=input.api_key,
208
+ messages=input.messages,
209
+ tools=input.tools,
210
+ invocation_parameters=input.invocation_parameters,
211
+ template=TemplateOptions(
212
+ language=input.template_language,
213
+ variables=revision.input,
214
+ ),
199
215
  ),
200
- ),
201
- )
202
- for revision in revisions
203
- ),
204
- return_exceptions=True,
205
- )
216
+ )
217
+ for revision in batch
218
+ ),
219
+ return_exceptions=True,
220
+ )
221
+ results.extend(batch_results)
206
222
 
207
223
  payload = ChatCompletionOverDatasetMutationPayload(
208
224
  dataset_id=GlobalID(models.Dataset.__name__, str(dataset.id)),
@@ -258,7 +274,7 @@ class ChatCompletionMutationMixin:
258
274
  payload.examples.append(example_payload)
259
275
  return payload
260
276
 
261
- @strawberry.mutation
277
+ @strawberry.mutation(permission_classes=[IsNotReadOnly]) # type: ignore
262
278
  @classmethod
263
279
  async def chat_completion(
264
280
  cls, info: Info[Context, None], input: ChatCompletionInput
@@ -266,11 +282,19 @@ class ChatCompletionMutationMixin:
266
282
  provider_key = input.model.provider_key
267
283
  llm_client_class = PLAYGROUND_CLIENT_REGISTRY.get_client(provider_key, input.model.name)
268
284
  if llm_client_class is None:
269
- raise BadRequest(f"No LLM client registered for provider '{provider_key}'")
270
- llm_client = llm_client_class(
271
- model=input.model,
272
- api_key=input.api_key,
273
- )
285
+ raise BadRequest(f"Unknown LLM provider: '{provider_key.value}'")
286
+ try:
287
+ llm_client = llm_client_class(
288
+ model=input.model,
289
+ api_key=input.api_key,
290
+ )
291
+ except CustomGraphQLError:
292
+ raise
293
+ except Exception as error:
294
+ raise BadRequest(
295
+ f"Failed to connect to LLM API for {provider_key.value} {input.model.name}: "
296
+ f"{str(error)}"
297
+ )
274
298
  return await cls._chat_completion(info, llm_client, input)
275
299
 
276
300
  @classmethod
@@ -459,6 +483,8 @@ def _template_formatter(template_language: TemplateLanguage) -> TemplateFormatte
459
483
  return MustacheTemplateFormatter()
460
484
  if template_language is TemplateLanguage.F_STRING:
461
485
  return FStringTemplateFormatter()
486
+ if template_language is TemplateLanguage.NONE:
487
+ return NoOpFormatter()
462
488
  assert_never(template_language)
463
489
 
464
490
 
@@ -486,6 +512,11 @@ def _llm_output_messages(
486
512
  if text_content:
487
513
  yield f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_CONTENT}", text_content
488
514
  for tool_call_index, tool_call in enumerate(tool_calls.values()):
515
+ if tool_call_id := tool_call.id:
516
+ yield (
517
+ f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_ID}",
518
+ tool_call_id,
519
+ )
489
520
  yield (
490
521
  f"{LLM_OUTPUT_MESSAGES}.0.{MESSAGE_TOOL_CALLS}.{tool_call_index}.{TOOL_CALL_FUNCTION_NAME}",
491
522
  tool_call.function.name,
@@ -513,6 +544,19 @@ def _serialize_event(event: SpanException) -> dict[str, Any]:
513
544
  return {k: (v.isoformat() if isinstance(v, datetime) else v) for k, v in asdict(event).items()}
514
545
 
515
546
 
547
+ _AnyT = TypeVar("_AnyT")
548
+
549
+
550
+ def _get_batches(
551
+ iterable: Iterable[_AnyT],
552
+ batch_size: int,
553
+ ) -> Iterator[list[_AnyT]]:
554
+ """Splits an iterable into batches not exceeding a specified size."""
555
+ iterator = iter(iterable)
556
+ while batch := list(islice(iterator, batch_size)):
557
+ yield batch
558
+
559
+
516
560
  JSON = OpenInferenceMimeTypeValues.JSON.value
517
561
  TEXT = OpenInferenceMimeTypeValues.TEXT.value
518
562
  LLM = OpenInferenceSpanKindValues.LLM.value
@@ -534,6 +578,7 @@ MESSAGE_CONTENT = MessageAttributes.MESSAGE_CONTENT
534
578
  MESSAGE_ROLE = MessageAttributes.MESSAGE_ROLE
535
579
  MESSAGE_TOOL_CALLS = MessageAttributes.MESSAGE_TOOL_CALLS
536
580
 
581
+ TOOL_CALL_ID = ToolCallAttributes.TOOL_CALL_ID
537
582
  TOOL_CALL_FUNCTION_NAME = ToolCallAttributes.TOOL_CALL_FUNCTION_NAME
538
583
  TOOL_CALL_FUNCTION_ARGUMENTS_JSON = ToolCallAttributes.TOOL_CALL_FUNCTION_ARGUMENTS_JSON
539
584