arize-phoenix 4.24.0__tar.gz → 4.25.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 (308) hide show
  1. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/.gitignore +3 -0
  2. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/PKG-INFO +10 -6
  3. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/README.md +1 -2
  4. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/frontend/requirements.txt +1 -1
  5. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/pyproject.toml +18 -13
  6. arize_phoenix-4.25.0/src/phoenix/auth/utils.py +15 -0
  7. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/engines.py +15 -2
  8. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/dataset.py +1 -0
  9. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrate.py +21 -10
  10. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/future_versions/cd164e83824f_users_and_tokens.py +7 -6
  11. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +4 -12
  12. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/models.py +1 -1
  13. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/inferences/fixtures.py +1 -0
  14. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/inferences/inferences.py +1 -0
  15. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/__init__.py +1 -0
  16. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/context.py +14 -0
  17. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/__init__.py +2 -0
  18. arize_phoenix-4.25.0/src/phoenix/server/api/mutations/api_key_mutations.py +119 -0
  19. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/auth.py +7 -0
  20. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/queries.py +7 -6
  21. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/datasets.py +1 -0
  22. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/spans.py +1 -1
  23. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/UserRole.py +1 -1
  24. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/app.py +36 -7
  25. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/main.py +24 -19
  26. arize_phoenix-4.25.0/src/phoenix/server/static/.vite/manifest.json +78 -0
  27. arize_phoenix-4.24.0/src/phoenix/server/static/assets/components-DzA9gIHT.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/components-1Ahruijo.js +4 -4
  28. arize_phoenix-4.24.0/src/phoenix/server/static/assets/index-BuTlV4Gk.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/index-BEE_RWJx.js +2 -2
  29. arize_phoenix-4.24.0/src/phoenix/server/static/assets/pages-DzkUGFGV.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/pages-CFS6mPnW.js +263 -220
  30. arize_phoenix-4.24.0/src/phoenix/server/static/assets/vendor-CIqy43_9.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/vendor-aSQri0vz.js +58 -58
  31. arize_phoenix-4.24.0/src/phoenix/server/static/assets/vendor-arizeai-B1YgcWL8.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/vendor-arizeai-CsdcB1NH.js +1 -1
  32. arize_phoenix-4.24.0/src/phoenix/server/static/assets/vendor-codemirror-_bcwCA1C.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/vendor-codemirror-CYHkhs7D.js +1 -1
  33. arize_phoenix-4.24.0/src/phoenix/server/static/assets/vendor-recharts-C3pM_Wlg.js → arize_phoenix-4.25.0/src/phoenix/server/static/assets/vendor-recharts-B0sannek.js +1 -1
  34. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/types.py +12 -4
  35. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/services.py +1 -0
  36. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/session/client.py +1 -1
  37. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/session/evaluation.py +1 -0
  38. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/session/session.py +2 -1
  39. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/fixtures.py +37 -0
  40. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/langchain/instrumentor.py +1 -1
  41. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/llama_index/callback.py +1 -0
  42. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/openai/instrumentor.py +1 -0
  43. arize_phoenix-4.25.0/src/phoenix/utilities/span_store.py +0 -0
  44. arize_phoenix-4.25.0/src/phoenix/version.py +1 -0
  45. arize_phoenix-4.24.0/src/phoenix/server/static/.vite/manifest.json +0 -78
  46. arize_phoenix-4.24.0/src/phoenix/version.py +0 -1
  47. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/IP_NOTICE +0 -0
  48. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/LICENSE +0 -0
  49. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/chat-service/chat/__init__.py +0 -0
  50. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/chat-service/chat/app.py +0 -0
  51. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/chat-service/chat/types.py +0 -0
  52. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/frontend/Dockerfile +0 -0
  53. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/frontend/Makefile +0 -0
  54. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/frontend/__init__.py +0 -0
  55. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/frontend/pyproject.toml +0 -0
  56. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/examples/manually-instrumented-chatbot/frontend/schema.json +0 -0
  57. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/__init__.py +0 -0
  58. {arize_phoenix-4.24.0/src/phoenix/core → arize_phoenix-4.25.0/src/phoenix/auth}/__init__.py +0 -0
  59. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/config.py +0 -0
  60. {arize_phoenix-4.24.0/src/phoenix/db/insertion → arize_phoenix-4.25.0/src/phoenix/core}/__init__.py +0 -0
  61. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/core/embedding_dimension.py +0 -0
  62. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/core/model.py +0 -0
  63. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/core/model_schema.py +0 -0
  64. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/core/model_schema_adapter.py +0 -0
  65. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/datetime_utils.py +0 -0
  66. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/README.md +0 -0
  67. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/__init__.py +0 -0
  68. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/alembic.ini +0 -0
  69. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/bulk_inserter.py +0 -0
  70. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/helpers.py +0 -0
  71. {arize_phoenix-4.24.0/src/phoenix/db/migrations → arize_phoenix-4.25.0/src/phoenix/db/insertion}/__init__.py +0 -0
  72. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/constants.py +0 -0
  73. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/document_annotation.py +0 -0
  74. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/evaluation.py +0 -0
  75. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/helpers.py +0 -0
  76. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/span.py +0 -0
  77. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/span_annotation.py +0 -0
  78. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/trace_annotation.py +0 -0
  79. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/insertion/types.py +0 -0
  80. {arize_phoenix-4.24.0/src/phoenix/inferences → arize_phoenix-4.25.0/src/phoenix/db/migrations}/__init__.py +0 -0
  81. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/env.py +0 -0
  82. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/future_versions/README.md +0 -0
  83. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/script.py.mako +0 -0
  84. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/versions/.gitignore +0 -0
  85. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
  86. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
  87. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/exceptions.py +0 -0
  88. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/__init__.py +0 -0
  89. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
  90. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/evaluators/base.py +0 -0
  91. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
  92. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
  93. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
  94. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/functions.py +0 -0
  95. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/tracing.py +0 -0
  96. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/types.py +0 -0
  97. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/experiments/utils.py +0 -0
  98. {arize_phoenix-4.24.0/src/phoenix/server → arize_phoenix-4.25.0/src/phoenix/inferences}/__init__.py +0 -0
  99. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/inferences/errors.py +0 -0
  100. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/inferences/schema.py +0 -0
  101. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/inferences/validation.py +0 -0
  102. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/README.md +0 -0
  103. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/binning.py +0 -0
  104. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/metrics.py +0 -0
  105. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/mixins.py +0 -0
  106. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
  107. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/timeseries.py +0 -0
  108. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/metrics/wrappers.py +0 -0
  109. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/pointcloud/__init__.py +0 -0
  110. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/pointcloud/clustering.py +0 -0
  111. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
  112. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/pointcloud/projectors.py +0 -0
  113. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
  114. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/py.typed +0 -0
  115. {arize_phoenix-4.24.0/src/phoenix/server/api → arize_phoenix-4.25.0/src/phoenix/server}/__init__.py +0 -0
  116. {arize_phoenix-4.24.0/src/phoenix/server/api/input_types → arize_phoenix-4.25.0/src/phoenix/server/api}/__init__.py +0 -0
  117. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/__init__.py +0 -0
  118. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/annotation_summaries.py +0 -0
  119. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +0 -0
  120. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
  121. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
  122. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -0
  123. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +0 -0
  124. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +0 -0
  125. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +0 -0
  126. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +0 -0
  127. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +0 -0
  128. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +0 -0
  129. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +0 -0
  130. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +0 -0
  131. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +0 -0
  132. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +0 -0
  133. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/project_by_name.py +0 -0
  134. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/record_counts.py +0 -0
  135. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/span_annotations.py +0 -0
  136. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/span_dataset_examples.py +0 -0
  137. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/span_descendants.py +0 -0
  138. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/span_projects.py +0 -0
  139. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/token_counts.py +0 -0
  140. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/dataloaders/trace_row_ids.py +0 -0
  141. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
  142. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
  143. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
  144. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
  145. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
  146. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
  147. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
  148. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
  149. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
  150. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
  151. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
  152. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
  153. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
  154. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
  155. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
  156. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
  157. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
  158. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
  159. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
  160. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
  161. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
  162. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
  163. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
  164. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
  165. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
  166. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/SpanAnnotationSort.py +0 -0
  167. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
  168. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
  169. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/input_types/TraceAnnotationSort.py +0 -0
  170. {arize_phoenix-4.24.0/src/phoenix/server/api/openapi → arize_phoenix-4.25.0/src/phoenix/server/api/input_types}/__init__.py +0 -0
  171. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/interceptor.py +0 -0
  172. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
  173. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
  174. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
  175. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
  176. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +0 -0
  177. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +0 -0
  178. {arize_phoenix-4.24.0/src/phoenix/server/api/routers → arize_phoenix-4.25.0/src/phoenix/server/api/openapi}/__init__.py +0 -0
  179. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/openapi/main.py +0 -0
  180. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/openapi/schema.py +0 -0
  181. {arize_phoenix-4.24.0/src/phoenix/server/api/types → arize_phoenix-4.25.0/src/phoenix/server/api/routers}/__init__.py +0 -0
  182. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/utils.py +0 -0
  183. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/__init__.py +0 -0
  184. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/evaluations.py +0 -0
  185. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -0
  186. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -0
  187. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/experiments.py +0 -0
  188. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/pydantic_compat.py +0 -0
  189. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/traces.py +0 -0
  190. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/routers/v1/utils.py +0 -0
  191. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/schema.py +0 -0
  192. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Annotation.py +0 -0
  193. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/AnnotationSummary.py +0 -0
  194. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
  195. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ApiKey.py +0 -0
  196. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Cluster.py +0 -0
  197. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
  198. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
  199. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Dataset.py +0 -0
  200. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
  201. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
  202. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
  203. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
  204. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Dimension.py +0 -0
  205. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
  206. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
  207. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
  208. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
  209. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
  210. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
  211. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
  212. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
  213. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
  214. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
  215. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Event.py +0 -0
  216. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
  217. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
  218. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Experiment.py +0 -0
  219. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
  220. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
  221. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
  222. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
  223. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
  224. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Functionality.py +0 -0
  225. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Inferences.py +0 -0
  226. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
  227. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/LabelFraction.py +0 -0
  228. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/MimeType.py +0 -0
  229. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Model.py +0 -0
  230. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
  231. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
  232. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Project.py +0 -0
  233. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
  234. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
  235. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
  236. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Segments.py +0 -0
  237. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/SortDir.py +0 -0
  238. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Span.py +0 -0
  239. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
  240. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/SystemApiKey.py +0 -0
  241. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
  242. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/Trace.py +0 -0
  243. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
  244. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
  245. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/User.py +0 -0
  246. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/UserApiKey.py +0 -0
  247. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
  248. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
  249. {arize_phoenix-4.24.0/src/phoenix/server/openapi → arize_phoenix-4.25.0/src/phoenix/server/api/types}/__init__.py +0 -0
  250. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/node.py +0 -0
  251. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/types/pagination.py +0 -0
  252. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/api/utils.py +0 -0
  253. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/dml_event.py +0 -0
  254. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/dml_event_handler.py +0 -0
  255. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/grpc_server.py +0 -0
  256. {arize_phoenix-4.24.0/src/phoenix/server/templates → arize_phoenix-4.25.0/src/phoenix/server/openapi}/__init__.py +0 -0
  257. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/prometheus.py +0 -0
  258. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
  259. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
  260. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
  261. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
  262. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
  263. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
  264. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
  265. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
  266. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/assets/vendor-DxkFTwjz.css +0 -0
  267. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/assets/vendor-three-DwGkEfCM.js +0 -0
  268. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/favicon.ico +0 -0
  269. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/static/modernizr.js +0 -0
  270. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/telemetry.py +0 -0
  271. {arize_phoenix-4.24.0/src/phoenix/session → arize_phoenix-4.25.0/src/phoenix/server/templates}/__init__.py +0 -0
  272. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/templates/index.html +0 -0
  273. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/server/thread_server.py +0 -0
  274. {arize_phoenix-4.24.0/src/phoenix/utilities → arize_phoenix-4.25.0/src/phoenix/session}/__init__.py +0 -0
  275. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/session/data_extractor.py +0 -0
  276. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/settings.py +0 -0
  277. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/__init__.py +0 -0
  278. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/attributes.py +0 -0
  279. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/dsl/README.md +0 -0
  280. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/dsl/__init__.py +0 -0
  281. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/dsl/filter.py +0 -0
  282. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/dsl/helpers.py +0 -0
  283. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/dsl/query.py +0 -0
  284. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/errors.py +0 -0
  285. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
  286. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/exporter.py +0 -0
  287. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/langchain/__init__.py +0 -0
  288. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/llama_index/__init__.py +0 -0
  289. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/openai/__init__.py +0 -0
  290. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/otel.py +0 -0
  291. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/projects.py +0 -0
  292. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/schemas.py +0 -0
  293. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/span_evaluations.py +0 -0
  294. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/span_json_decoder.py +0 -0
  295. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/span_json_encoder.py +0 -0
  296. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/trace_dataset.py +0 -0
  297. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/utils.py +0 -0
  298. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/v1/__init__.py +0 -0
  299. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
  300. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
  301. /arize_phoenix-4.24.0/src/phoenix/utilities/span_store.py → /arize_phoenix-4.25.0/src/phoenix/utilities/__init__.py +0 -0
  302. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/client.py +0 -0
  303. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/deprecation.py +0 -0
  304. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/error_handling.py +0 -0
  305. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/json.py +0 -0
  306. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/logging.py +0 -0
  307. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/project.py +0 -0
  308. {arize_phoenix-4.24.0 → arize_phoenix-4.25.0}/src/phoenix/utilities/re.py +0 -0
@@ -25,3 +25,6 @@ coverage.xml
25
25
 
26
26
  # devtools
27
27
  pyrightconfig.json
28
+
29
+ # Demo data
30
+ tutorials/internal/demo_llama_index/*.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arize-phoenix
3
- Version: 4.24.0
3
+ Version: 4.25.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
@@ -42,9 +42,11 @@ Requires-Dist: protobuf<6.0,>=3.20
42
42
  Requires-Dist: psutil
43
43
  Requires-Dist: pyarrow
44
44
  Requires-Dist: pydantic!=2.0.*,<3,>=1.0
45
+ Requires-Dist: pyjwt
45
46
  Requires-Dist: python-multipart
46
47
  Requires-Dist: scikit-learn
47
- Requires-Dist: scipy
48
+ Requires-Dist: scipy!=1.14.1; platform_system == 'Darwin'
49
+ Requires-Dist: scipy; platform_system != 'Darwin'
48
50
  Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
49
51
  Requires-Dist: sqlean-py>=3.45.1
50
52
  Requires-Dist: starlette
@@ -85,14 +87,16 @@ Requires-Dist: nbqa; extra == 'dev'
85
87
  Requires-Dist: pandas-stubs==2.0.3.230814; (python_version < '3.9') and extra == 'dev'
86
88
  Requires-Dist: pandas-stubs==2.2.2.240603; (python_version >= '3.9') and extra == 'dev'
87
89
  Requires-Dist: pandas>=1.0; extra == 'dev'
90
+ Requires-Dist: portpicker; extra == 'dev'
88
91
  Requires-Dist: pre-commit; extra == 'dev'
89
92
  Requires-Dist: prometheus-client; extra == 'dev'
90
93
  Requires-Dist: psycopg[binary]; extra == 'dev'
91
94
  Requires-Dist: pytest-asyncio; extra == 'dev'
92
95
  Requires-Dist: pytest-cov; extra == 'dev'
93
96
  Requires-Dist: pytest-postgresql; extra == 'dev'
94
- Requires-Dist: pytest==8.3.1; extra == 'dev'
95
- Requires-Dist: ruff==0.5.4; extra == 'dev'
97
+ Requires-Dist: pytest-xdist; extra == 'dev'
98
+ Requires-Dist: pytest==8.3.2; extra == 'dev'
99
+ Requires-Dist: ruff==0.6.1; extra == 'dev'
96
100
  Requires-Dist: strawberry-graphql[debug-server,opentelemetry]==0.236.0; extra == 'dev'
97
101
  Requires-Dist: tabulate; extra == 'dev'
98
102
  Requires-Dist: types-tabulate; extra == 'dev'
@@ -107,6 +111,7 @@ Requires-Dist: llama-index-readers-file==0.1.25; extra == 'llama-index'
107
111
  Requires-Dist: llama-index==0.10.51; extra == 'llama-index'
108
112
  Provides-Extra: pg
109
113
  Requires-Dist: asyncpg; extra == 'pg'
114
+ Provides-Extra: test
110
115
  Description-Content-Type: text/markdown
111
116
 
112
117
  <p align="center">
@@ -144,9 +149,8 @@ Phoenix is an open-source AI observability platform designed for experimentation
144
149
  - **_Evaluation_** - Leverage LLMs to benchmark your application's performance using response and retrieval evals.
145
150
  - **_Datasets_** - Create versioned datasets of examples for experimentation, evaluation, and fine-tuning.
146
151
  - **_Experiments_** - Track and evaluate changes to prompts, LLMs, and retrieval.
147
- - **_Inference Analysis_** - Visualize inferences and embeddings using dimensionality reduction and clustering to identify drift and performance degradation.
148
152
 
149
- Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙LlamaIndex, 🦜⛓LangChain, 🧩DSPy) and LLM providers (OpenAI, Bedrock, and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
153
+ Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙LlamaIndex, 🦜⛓LangChain, Haystack, 🧩DSPy) and LLM providers (OpenAI, Bedrock, and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
150
154
 
151
155
  Phoenix runs practically anywhere, including your Jupyter notebook, local machine, containerized deployment, or in the cloud.
152
156
 
@@ -33,9 +33,8 @@ Phoenix is an open-source AI observability platform designed for experimentation
33
33
  - **_Evaluation_** - Leverage LLMs to benchmark your application's performance using response and retrieval evals.
34
34
  - **_Datasets_** - Create versioned datasets of examples for experimentation, evaluation, and fine-tuning.
35
35
  - **_Experiments_** - Track and evaluate changes to prompts, LLMs, and retrieval.
36
- - **_Inference Analysis_** - Visualize inferences and embeddings using dimensionality reduction and clustering to identify drift and performance degradation.
37
36
 
38
- Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙LlamaIndex, 🦜⛓LangChain, 🧩DSPy) and LLM providers (OpenAI, Bedrock, and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
37
+ Phoenix is vendor and language agnostic with out-of-the-box support for popular frameworks (🦙LlamaIndex, 🦜⛓LangChain, Haystack, 🧩DSPy) and LLM providers (OpenAI, Bedrock, and more). For details on auto-instrumentation, check out the [OpenInference](https://github.com/Arize-ai/openinference) project.
39
38
 
40
39
  Phoenix runs practically anywhere, including your Jupyter notebook, local machine, containerized deployment, or in the cloud.
41
40
 
@@ -14,7 +14,7 @@ blinker==1.7.0
14
14
  # via streamlit
15
15
  cachetools==5.3.3
16
16
  # via streamlit
17
- certifi==2024.2.2
17
+ certifi==2024.7.4
18
18
  # via
19
19
  # httpcore
20
20
  # httpx
@@ -36,7 +36,8 @@ dependencies = [
36
36
  "typing-extensions>=4.5; python_version<'3.12'",
37
37
  # A minimum version of typing-extensions==4.6.0 is needed to avoid this issue on Python 3.12: https://github.com/Azure/azure-sdk-for-python/issues/33442#issuecomment-1847886784
38
38
  "typing-extensions>=4.6; python_version>='3.12'",
39
- "scipy",
39
+ "scipy!=1.14.1; platform_system == 'Darwin'", # MacOS installation issue: https://github.com/scipy/scipy/issues/21424
40
+ "scipy; platform_system != 'Darwin'",
40
41
  "wrapt",
41
42
  "protobuf>=3.20, <6.0",
42
43
  "grpcio",
@@ -60,7 +61,8 @@ dependencies = [
60
61
  "python-multipart", # see https://www.starlette.io/#dependencies
61
62
  "arize-phoenix-evals>=0.13.1",
62
63
  "fastapi",
63
- "pydantic>=1.0,!=2.0.*,<3,", # exclude 2.0.* since it does not support the `json_encoders` configuration setting
64
+ "pydantic>=1.0,!=2.0.*,<3", # exclude 2.0.* since it does not support the `json_encoders` configuration setting
65
+ "pyjwt",
64
66
  ]
65
67
  dynamic = ["version"]
66
68
 
@@ -70,14 +72,15 @@ dev = [
70
72
  "hatch",
71
73
  "jupyter",
72
74
  "nbqa",
73
- "ruff==0.5.4",
75
+ "ruff==0.6.1",
74
76
  "mypy==1.11.1",
75
77
  "pandas>=1.0",
76
78
  "tabulate", # used by DataFrame.to_markdown()
77
79
  "types-tabulate",
78
80
  "pandas-stubs==2.2.2.240603; python_version>='3.9'",
79
81
  "pandas-stubs==2.0.3.230814; python_version<'3.9'",
80
- "pytest==8.3.1",
82
+ "pytest==8.3.2",
83
+ "pytest-xdist",
81
84
  "pytest-asyncio",
82
85
  "pytest-cov",
83
86
  "pytest-postgresql",
@@ -94,6 +97,7 @@ dev = [
94
97
  "prometheus_client",
95
98
  "asgi-lifespan",
96
99
  "Faker>=26.0.0",
100
+ "portpicker",
97
101
  "uvloop; platform_system != 'Windows'",
98
102
  ]
99
103
  evals = []
@@ -121,6 +125,8 @@ container = [
121
125
  "strawberry-graphql[opentelemetry]==0.236.0", # need to pin version because we're monkey-patching
122
126
  "uvloop; platform_system != 'Windows'",
123
127
  ]
128
+ test = [
129
+ ]
124
130
 
125
131
  [project.urls]
126
132
  Documentation = "https://docs.arize.com/phoenix/"
@@ -151,7 +157,8 @@ dependencies = [
151
157
  "numpy",
152
158
  "pandas==2.2.2; python_version>='3.9'",
153
159
  "pandas==1.4.0; python_version<'3.9'",
154
- "pytest==8.3.1",
160
+ "pytest==8.3.2",
161
+ "pytest-xdist",
155
162
  "pytest-asyncio",
156
163
  "pytest-cov",
157
164
  "pytest-postgresql",
@@ -179,7 +186,7 @@ dependencies = [
179
186
 
180
187
  [tool.hatch.envs.type]
181
188
  dependencies = [
182
- "mypy==1.11.0",
189
+ "mypy==1.11.1",
183
190
  "tenacity",
184
191
  "pandas>=1.0",
185
192
  "pandas-stubs==2.0.3.230814",
@@ -214,7 +221,7 @@ python = ["3.8", "3.9", "3.12"]
214
221
  [tool.hatch.envs.style]
215
222
  detached = true
216
223
  dependencies = [
217
- "ruff==0.5.4",
224
+ "ruff==0.6.1",
218
225
  ]
219
226
 
220
227
  [[tool.hatch.envs.style.matrix]]
@@ -234,7 +241,7 @@ dependencies = [
234
241
  ]
235
242
 
236
243
  [tool.hatch.envs.default.scripts]
237
- tests = "pytest {args}"
244
+ tests = "pytest -n auto {args}"
238
245
  coverage = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=src/phoenix --cov=tests {args}"
239
246
 
240
247
  [[tool.hatch.envs.test.matrix]]
@@ -246,6 +253,8 @@ addopts = [
246
253
  "-rA",
247
254
  "--import-mode=importlib",
248
255
  "--doctest-modules",
256
+ "--new-first",
257
+ "--showlocals",
249
258
  ]
250
259
  testpaths = [
251
260
  "tests",
@@ -363,9 +372,6 @@ ignore-setters = false
363
372
 
364
373
  [tool.mypy]
365
374
  plugins = ["strawberry.ext.mypy_plugin", "pydantic.mypy"]
366
- disallow_untyped_calls = true
367
- disallow_untyped_defs = true
368
- disallow_incomplete_defs = true
369
375
  strict = true
370
376
  exclude = [
371
377
  "api_reference",
@@ -413,7 +419,6 @@ exclude = [
413
419
  "*.pyi",
414
420
  "docs/",
415
421
  ]
416
- extend-include = ["*.ipynb"]
417
422
  line-length = 100
418
423
  target-version = "py38"
419
424
 
@@ -427,4 +432,4 @@ select = ["E", "F", "W", "I", "NPY201"]
427
432
  force-single-line = false
428
433
 
429
434
  [tool.ruff.format]
430
- line-ending = "lf"
435
+ line-ending = "native"
@@ -0,0 +1,15 @@
1
+ from hashlib import pbkdf2_hmac
2
+
3
+
4
+ def compute_password_hash(password: str, salt: str) -> str:
5
+ """
6
+ Salts and hashes a password using PBKDF2, HMAC, and SHA256.
7
+ """
8
+ password_bytes = password.encode("utf-8")
9
+ salt_bytes = salt.encode("utf-8")
10
+ password_hash_bytes = pbkdf2_hmac("sha256", password_bytes, salt_bytes, NUM_ITERATIONS)
11
+ password_hash = password_hash_bytes.hex()
12
+ return password_hash
13
+
14
+
15
+ NUM_ITERATIONS = 1_000_000
@@ -7,6 +7,7 @@ from typing import Any
7
7
 
8
8
  import aiosqlite
9
9
  import numpy as np
10
+ import sqlalchemy
10
11
  import sqlean
11
12
  from sqlalchemy import URL, StaticPool, event, make_url
12
13
  from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
@@ -15,6 +16,7 @@ from typing_extensions import assert_never
15
16
  from phoenix.db.helpers import SupportedSQLDialect
16
17
  from phoenix.db.migrate import migrate_in_thread
17
18
  from phoenix.db.models import init_models
19
+ from phoenix.settings import Settings
18
20
 
19
21
  sqlean.extensions.enable("text", "stats")
20
22
 
@@ -118,7 +120,13 @@ def aio_sqlite_engine(
118
120
  else:
119
121
  asyncio.create_task(init_models(engine))
120
122
  else:
121
- migrate_in_thread(engine.url)
123
+ sync_engine = sqlalchemy.create_engine(
124
+ url=url.set(drivername="sqlite"),
125
+ echo=Settings.log_migrations,
126
+ json_serializer=_dumps,
127
+ creator=lambda: sqlean.connect(f"file:{database}", uri=True),
128
+ )
129
+ migrate_in_thread(sync_engine)
122
130
  return engine
123
131
 
124
132
 
@@ -130,7 +138,12 @@ def aio_postgresql_engine(
130
138
  engine = create_async_engine(url=url, echo=echo, json_serializer=_dumps)
131
139
  if not migrate:
132
140
  return engine
133
- migrate_in_thread(engine.url)
141
+ sync_engine = sqlalchemy.create_engine(
142
+ url=url.set(drivername="postgresql"),
143
+ echo=Settings.log_migrations,
144
+ json_serializer=_dumps,
145
+ )
146
+ migrate_in_thread(sync_engine)
134
147
  return engine
135
148
 
136
149
 
@@ -24,6 +24,7 @@ from phoenix.db import models
24
24
  from phoenix.db.insertion.helpers import DataManipulationEvent
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
+ logger.addHandler(logging.NullHandler())
27
28
 
28
29
  DatasetId: TypeAlias = int
29
30
  DatasetVersionId: TypeAlias = int
@@ -1,25 +1,34 @@
1
+ import codecs
1
2
  import logging
3
+ import sys
2
4
  from pathlib import Path
3
- from queue import Empty, Queue
5
+ from queue import Empty, SimpleQueue
4
6
  from threading import Thread
5
7
  from typing import Optional
6
8
 
7
9
  from alembic import command
8
10
  from alembic.config import Config
9
- from sqlalchemy import URL
11
+ from sqlalchemy import Engine
10
12
 
11
13
  from phoenix.exceptions import PhoenixMigrationError
12
14
  from phoenix.settings import Settings
13
15
 
14
16
  logger = logging.getLogger(__name__)
17
+ logger.addHandler(logging.NullHandler())
15
18
 
16
19
 
17
20
  def printif(condition: bool, text: str) -> None:
18
- if condition:
19
- print(text)
21
+ if not condition:
22
+ return
23
+ if sys.platform.startswith("win"):
24
+ text = codecs.encode(text, "ascii", errors="ignore").decode("ascii").strip()
25
+ print(text)
20
26
 
21
27
 
22
- def migrate(url: URL, error_queue: Optional["Queue[Exception]"] = None) -> None:
28
+ def migrate(
29
+ engine: Engine,
30
+ error_queue: Optional["SimpleQueue[BaseException]"] = None,
31
+ ) -> None:
23
32
  """
24
33
  Runs migrations on the database.
25
34
  NB: Migrate only works on non-memory databases.
@@ -37,24 +46,26 @@ def migrate(url: URL, error_queue: Optional["Queue[Exception]"] = None) -> None:
37
46
  # Explicitly set the migration directory
38
47
  scripts_location = str(Path(__file__).parent.resolve() / "migrations")
39
48
  alembic_cfg.set_main_option("script_location", scripts_location)
40
- alembic_cfg.set_main_option("sqlalchemy.url", str(url).replace("%", "%%"))
49
+ url = str(engine.url).replace("%", "%%")
50
+ alembic_cfg.set_main_option("sqlalchemy.url", url)
51
+ alembic_cfg.attributes["connection"] = engine.connect()
41
52
  command.upgrade(alembic_cfg, "head")
42
53
  printif(log_migrations, "---------------------------")
43
54
  printif(log_migrations, "✅ Migrations complete.")
44
- except Exception as e:
55
+ except BaseException as e:
45
56
  if error_queue:
46
57
  error_queue.put(e)
47
58
  raise e
48
59
 
49
60
 
50
- def migrate_in_thread(url: URL) -> None:
61
+ def migrate_in_thread(engine: Engine) -> None:
51
62
  """
52
63
  Runs migrations on the database in a separate thread.
53
64
  This is needed because depending on the context (notebook)
54
65
  the migration process can fail to execute in the main thread.
55
66
  """
56
- error_queue: Queue[Exception] = Queue()
57
- t = Thread(target=migrate, args=(url, error_queue))
67
+ error_queue: SimpleQueue[BaseException] = SimpleQueue()
68
+ t = Thread(target=migrate, args=(engine, error_queue))
58
69
  t.start()
59
70
  t.join()
60
71
 
@@ -11,7 +11,6 @@ from typing import Any, Dict, List, Optional, Sequence, TypedDict, Union
11
11
 
12
12
  import sqlalchemy as sa
13
13
  from alembic import op
14
- from phoenix.datetime_utils import normalize_datetime
15
14
  from sqlalchemy import (
16
15
  JSON,
17
16
  TIMESTAMP,
@@ -32,6 +31,8 @@ from sqlalchemy.orm import (
32
31
  mapped_column,
33
32
  )
34
33
 
34
+ from phoenix.datetime_utils import normalize_datetime
35
+
35
36
 
36
37
  class JSONB(JSON):
37
38
  # See https://docs.sqlalchemy.org/en/20/core/custom_types.html
@@ -113,7 +114,7 @@ class Base(DeclarativeBase):
113
114
  class UserRole(Base):
114
115
  __tablename__ = "user_roles"
115
116
  id: Mapped[int] = mapped_column(primary_key=True)
116
- role: Mapped[str] = mapped_column(unique=True)
117
+ name: Mapped[str] = mapped_column(unique=True)
117
118
 
118
119
 
119
120
  class User(Base):
@@ -150,10 +151,10 @@ async def insert_roles_and_users(connection: AsyncConnection) -> None:
150
151
  user to the `users` table.
151
152
  """
152
153
  await connection.execute(
153
- insert(UserRole).values([{"role": "SYSTEM"}, {"role": "ADMIN"}, {"role": "MEMBER"}])
154
+ insert(UserRole).values([{"name": "SYSTEM"}, {"name": "ADMIN"}, {"name": "MEMBER"}])
154
155
  )
155
- system_user_role_id = sa.select(UserRole.id).where(UserRole.role == "SYSTEM").scalar_subquery()
156
- admin_user_role_id = sa.select(UserRole.id).where(UserRole.role == "ADMIN").scalar_subquery()
156
+ system_user_role_id = sa.select(UserRole.id).where(UserRole.name == "SYSTEM").scalar_subquery()
157
+ admin_user_role_id = sa.select(UserRole.id).where(UserRole.name == "ADMIN").scalar_subquery()
157
158
  await connection.execute(
158
159
  insert(User).values(
159
160
  [
@@ -183,7 +184,7 @@ def upgrade() -> None:
183
184
  "user_roles",
184
185
  sa.Column("id", sa.Integer, primary_key=True),
185
186
  sa.Column(
186
- "role",
187
+ "name",
187
188
  sa.String,
188
189
  nullable=False,
189
190
  unique=True,
@@ -19,7 +19,6 @@ from sqlalchemy import (
19
19
  update,
20
20
  )
21
21
  from sqlalchemy.dialects import postgresql
22
- from sqlalchemy.ext.asyncio.engine import AsyncConnection
23
22
  from sqlalchemy.ext.compiler import compiles
24
23
  from sqlalchemy.orm import (
25
24
  DeclarativeBase,
@@ -111,11 +110,10 @@ LLM_TOKEN_COUNT_PROMPT = SpanAttributes.LLM_TOKEN_COUNT_PROMPT.split(".")
111
110
  LLM_TOKEN_COUNT_COMPLETION = SpanAttributes.LLM_TOKEN_COUNT_COMPLETION.split(".")
112
111
 
113
112
 
114
- async def get_token_counts_from_attributes(connection: AsyncConnection) -> None:
115
- """
116
- Gets token counts from attributes if present.
117
- """
118
- await connection.execute(
113
+ def upgrade() -> None:
114
+ op.add_column("spans", sa.Column("llm_token_count_prompt", sa.Integer, nullable=True))
115
+ op.add_column("spans", sa.Column("llm_token_count_completion", sa.Integer, nullable=True))
116
+ op.execute(
119
117
  update(Span).values(
120
118
  llm_token_count_prompt=Span.attributes[LLM_TOKEN_COUNT_PROMPT].as_float(),
121
119
  llm_token_count_completion=Span.attributes[LLM_TOKEN_COUNT_COMPLETION].as_float(),
@@ -123,12 +121,6 @@ async def get_token_counts_from_attributes(connection: AsyncConnection) -> None:
123
121
  )
124
122
 
125
123
 
126
- def upgrade() -> None:
127
- op.add_column("spans", sa.Column("llm_token_count_prompt", sa.Integer, nullable=True))
128
- op.add_column("spans", sa.Column("llm_token_count_completion", sa.Integer, nullable=True))
129
- op.run_async(get_token_counts_from_attributes)
130
-
131
-
132
124
  def downgrade() -> None:
133
125
  op.drop_column("spans", "llm_token_count_completion")
134
126
  op.drop_column("spans", "llm_token_count_prompt")
@@ -625,7 +625,7 @@ if ENABLE_AUTH:
625
625
  class UserRole(Base):
626
626
  __tablename__ = "user_roles"
627
627
  id: Mapped[int] = mapped_column(primary_key=True)
628
- role: Mapped[str] = mapped_column(unique=True)
628
+ name: Mapped[str] = mapped_column(unique=True)
629
629
  users: Mapped[List["User"]] = relationship("User", back_populates="role")
630
630
 
631
631
  class User(Base):
@@ -18,6 +18,7 @@ from phoenix.inferences.schema import (
18
18
  )
19
19
 
20
20
  logger = logging.getLogger(__name__)
21
+ logger.addHandler(logging.NullHandler())
21
22
 
22
23
 
23
24
  class InferencesRole(Enum):
@@ -34,6 +34,7 @@ from .schema import (
34
34
  from .validation import validate_inferences_inputs
35
35
 
36
36
  logger = logging.getLogger(__name__)
37
+ logger.addHandler(logging.NullHandler())
37
38
 
38
39
  # A schema like object. Not recommended to use this directly
39
40
  SchemaLike: TypeAlias = Any
@@ -10,6 +10,7 @@ import pandas as pd
10
10
  from phoenix.core.model_schema import Column
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
+ logger.addHandler(logging.NullHandler())
13
14
 
14
15
 
15
16
  @dataclass(frozen=True)
@@ -74,3 +74,17 @@ class Context(BaseContext):
74
74
  event_queue: CanPutItem[DmlEvent] = _NoOp()
75
75
  corpus: Optional[Model] = None
76
76
  read_only: bool = False
77
+ secret: Optional[str] = None
78
+
79
+ def get_secret(self) -> str:
80
+ """A type safe way to get the application secret. Throws an error if the secret is not set.
81
+
82
+ Returns:
83
+ str: the phoenix secret
84
+ """
85
+ if self.secret is None:
86
+ raise ValueError(
87
+ "Application secret not set."
88
+ " Please set the PHOENIX_SECRET environment variable and re-deploy the application."
89
+ )
90
+ return self.secret
@@ -1,5 +1,6 @@
1
1
  import strawberry
2
2
 
3
+ from phoenix.server.api.mutations.api_key_mutations import ApiKeyMutationMixin
3
4
  from phoenix.server.api.mutations.dataset_mutations import DatasetMutationMixin
4
5
  from phoenix.server.api.mutations.experiment_mutations import ExperimentMutationMixin
5
6
  from phoenix.server.api.mutations.export_events_mutations import ExportEventsMutationMixin
@@ -16,5 +17,6 @@ class Mutation(
16
17
  ExportEventsMutationMixin,
17
18
  SpanAnnotationMutationMixin,
18
19
  TraceAnnotationMutationMixin,
20
+ ApiKeyMutationMixin,
19
21
  ):
20
22
  pass
@@ -0,0 +1,119 @@
1
+ from datetime import datetime
2
+ from typing import Any, Dict, Optional
3
+
4
+ import jwt
5
+ import strawberry
6
+ from sqlalchemy import insert, select
7
+ from strawberry import UNSET
8
+ from strawberry.types import Info
9
+
10
+ from phoenix.db import models
11
+ from phoenix.server.api.context import Context
12
+ from phoenix.server.api.mutations.auth import HasSecret, IsAuthenticated
13
+ from phoenix.server.api.queries import Query
14
+ from phoenix.server.api.types.SystemApiKey import SystemApiKey
15
+
16
+
17
+ @strawberry.type
18
+ class CreateSystemApiKeyMutationPayload:
19
+ jwt: str
20
+ api_key: SystemApiKey
21
+ query: Query
22
+
23
+
24
+ @strawberry.input
25
+ class CreateApiKeyInput:
26
+ name: str
27
+ description: Optional[str] = UNSET
28
+ expires_at: Optional[datetime] = UNSET
29
+
30
+
31
+ @strawberry.type
32
+ class ApiKeyMutationMixin:
33
+ @strawberry.mutation(permission_classes=[HasSecret, IsAuthenticated]) # type: ignore
34
+ async def create_system_api_key(
35
+ self, info: Info[Context, None], input: CreateApiKeyInput
36
+ ) -> CreateSystemApiKeyMutationPayload:
37
+ # TODO(auth): safe guard against auth being disabled and secret not being set
38
+ async with info.context.db() as session:
39
+ # Get the system user - note this could be pushed into a dataloader
40
+ system_user = await session.scalar(
41
+ select(models.User)
42
+ .join(models.UserRole) # Join User with UserRole
43
+ .where(models.UserRole.name == "SYSTEM") # Filter where role is SYSTEM
44
+ .limit(1)
45
+ )
46
+ if system_user is None:
47
+ raise ValueError("System user not found")
48
+
49
+ insert_stmt = (
50
+ insert(models.APIKey)
51
+ .values(
52
+ user_id=system_user.id,
53
+ name=input.name,
54
+ description=input.description or None,
55
+ expires_at=input.expires_at or None,
56
+ )
57
+ .returning(models.APIKey)
58
+ )
59
+ api_key = await session.scalar(insert_stmt)
60
+ assert api_key is not None
61
+
62
+ encoded_jwt = create_jwt(
63
+ secret=info.context.get_secret(),
64
+ name=api_key.name,
65
+ id=api_key.id,
66
+ description=api_key.description,
67
+ iat=api_key.created_at,
68
+ exp=api_key.expires_at,
69
+ )
70
+ return CreateSystemApiKeyMutationPayload(
71
+ jwt=encoded_jwt,
72
+ api_key=SystemApiKey(
73
+ id_attr=api_key.id,
74
+ name=api_key.name,
75
+ description=api_key.description,
76
+ created_at=api_key.created_at,
77
+ expires_at=api_key.expires_at,
78
+ ),
79
+ query=Query(),
80
+ )
81
+
82
+
83
+ def create_jwt(
84
+ *,
85
+ secret: str,
86
+ algorithm: str = "HS256",
87
+ name: str,
88
+ description: Optional[str],
89
+ iat: datetime,
90
+ exp: Optional[datetime],
91
+ id: int,
92
+ ) -> str:
93
+ """Create a signed JSON Web Token for authentication
94
+
95
+ Args:
96
+ secret (str): the secret to sign with
97
+ name (str): name of the key / token
98
+ description (Optional[str]): description of the token
99
+ iat (datetime): the issued at time
100
+ exp (Optional[datetime]): the expiry, if set
101
+ id (int): the id of the key
102
+ algorithm (str, optional): the algorithm to use. Defaults to "HS256".
103
+
104
+ Returns:
105
+ str: The encoded JWT
106
+ """
107
+ payload: Dict[str, Any] = {
108
+ "name": name,
109
+ "description": description,
110
+ "iat": iat.utcnow(),
111
+ "id": id,
112
+ }
113
+ if exp is not None:
114
+ payload["exp"] = exp.utcnow()
115
+
116
+ # Encode the payload to create the JWT
117
+ token = jwt.encode(payload, secret, algorithm=algorithm)
118
+
119
+ return token
@@ -9,3 +9,10 @@ class IsAuthenticated(BasePermission):
9
9
 
10
10
  async def has_permission(self, source: Any, info: Info, **kwargs: Any) -> bool:
11
11
  return not info.context.read_only
12
+
13
+
14
+ class HasSecret(BasePermission):
15
+ message = "Application secret is not set"
16
+
17
+ async def has_permission(self, source: Any, info: Info, **kwargs: Any) -> bool:
18
+ return info.context.secret is not None