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