arize-phoenix 4.14.1__tar.gz → 4.16.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-4.14.1 → arize_phoenix-4.16.0}/PKG-INFO +5 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/pyproject.toml +17 -7
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/bulk_inserter.py +131 -5
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/engines.py +2 -1
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/helpers.py +23 -1
- arize_phoenix-4.16.0/src/phoenix/db/insertion/constants.py +2 -0
- arize_phoenix-4.16.0/src/phoenix/db/insertion/document_annotation.py +157 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/insertion/helpers.py +13 -0
- arize_phoenix-4.16.0/src/phoenix/db/insertion/span_annotation.py +144 -0
- arize_phoenix-4.16.0/src/phoenix/db/insertion/trace_annotation.py +144 -0
- arize_phoenix-4.16.0/src/phoenix/db/insertion/types.py +261 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/functions.py +3 -2
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/types.py +3 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/context.py +7 -9
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/__init__.py +2 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/average_experiment_run_latency.py +3 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/dataset_example_revisions.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/dataset_example_spans.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/document_evaluations.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/document_retrieval_metrics.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/evaluation_summaries.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/experiment_annotation_summaries.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/experiment_error_rates.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/experiment_run_counts.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/experiment_sequence_number.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/latency_ms_quantile.py +2 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/min_start_or_max_end_times.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/project_by_name.py +3 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/record_counts.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/span_annotations.py +2 -4
- arize_phoenix-4.16.0/src/phoenix/server/api/dataloaders/span_dataset_examples.py +36 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/span_descendants.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/span_evaluations.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/span_projects.py +3 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/token_counts.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/trace_evaluations.py +2 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/trace_row_ids.py +2 -4
- arize_phoenix-4.16.0/src/phoenix/server/api/input_types/SpanAnnotationSort.py +17 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/input_types/TraceAnnotationSort.py +17 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/span_annotations_mutations.py +8 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/trace_annotations_mutations.py +8 -3
- arize_phoenix-4.16.0/src/phoenix/server/api/openapi/main.py +22 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/openapi/schema.py +16 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/__init__.py +42 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/datasets.py +1029 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/routers/v1/evaluations.py +164 -73
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/experiment_evaluations.py +113 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/experiment_runs.py +160 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/experiments.py +252 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/pydantic_compat.py +78 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/spans.py +236 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/traces.py +203 -0
- arize_phoenix-4.16.0/src/phoenix/server/api/routers/v1/utils.py +95 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Span.py +27 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Trace.py +21 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/utils.py +4 -4
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/app.py +172 -192
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/grpc_server.py +2 -2
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/main.py +5 -9
- arize_phoenix-4.16.0/src/phoenix/server/static/.vite/manifest.json +78 -0
- arize_phoenix-4.16.0/src/phoenix/server/static/assets/components-Ci5kMOk5.js +1175 -0
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/index-CQgXRwU0.js → arize_phoenix-4.16.0/src/phoenix/server/static/assets/index-BQG5WVX7.js +2 -2
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/pages-hdjlFZhO.js → arize_phoenix-4.16.0/src/phoenix/server/static/assets/pages-BrevprVW.js +451 -275
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/vendor-DPvSDRn3.js → arize_phoenix-4.16.0/src/phoenix/server/static/assets/vendor-CP0b0YG0.js +2 -2
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/vendor-arizeai-CkvPT67c.js → arize_phoenix-4.16.0/src/phoenix/server/static/assets/vendor-arizeai-DTbiPGp6.js +27 -27
- arize_phoenix-4.16.0/src/phoenix/server/static/assets/vendor-codemirror-DtdPDzrv.js +15 -0
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/vendor-recharts-5jlNaZuF.js → arize_phoenix-4.16.0/src/phoenix/server/static/assets/vendor-recharts-A0DA1O99.js +1 -1
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/thread_server.py +2 -2
- arize_phoenix-4.16.0/src/phoenix/server/types.py +18 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/session/client.py +5 -3
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/session/session.py +2 -2
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/dsl/filter.py +2 -6
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/fixtures.py +17 -23
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/utils.py +23 -0
- arize_phoenix-4.16.0/src/phoenix/utilities/client.py +116 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/project.py +1 -1
- arize_phoenix-4.16.0/src/phoenix/version.py +1 -0
- arize_phoenix-4.14.1/src/phoenix/server/api/openapi/main.py +0 -6
- arize_phoenix-4.14.1/src/phoenix/server/api/openapi/schema.py +0 -16
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/__init__.py +0 -89
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/dataset_examples.py +0 -178
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/datasets.py +0 -1023
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/experiment_evaluations.py +0 -136
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/experiment_runs.py +0 -217
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/experiments.py +0 -301
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/spans.py +0 -275
- arize_phoenix-4.14.1/src/phoenix/server/api/routers/v1/traces.py +0 -228
- arize_phoenix-4.14.1/src/phoenix/server/openapi/docs.py +0 -221
- arize_phoenix-4.14.1/src/phoenix/server/static/.vite/manifest.json +0 -78
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/components-DeS0YEmv.js +0 -1142
- arize_phoenix-4.14.1/src/phoenix/server/static/assets/vendor-codemirror-Cqwpwlua.js +0 -12
- arize_phoenix-4.14.1/src/phoenix/version.py +0 -1
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/.gitignore +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/IP_NOTICE +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/LICENSE +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/README.md +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/chat-service/chat/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/chat-service/chat/app.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/chat-service/chat/types.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/frontend/Dockerfile +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/frontend/Makefile +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/frontend/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/frontend/pyproject.toml +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/frontend/requirements.txt +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/examples/manually-instrumented-chatbot/frontend/schema.json +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/config.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/core/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/core/embedding_dimension.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/core/model.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/core/model_schema.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/core/model_schema_adapter.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/datetime_utils.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/README.md +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/alembic.ini +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/insertion/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/insertion/dataset.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/insertion/evaluation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/insertion/span.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrate.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrations/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrations/env.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrations/script.py.mako +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrations/types.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrations/versions/10460e46d750_datasets.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/migrations/versions/cf03bd6bae1d_init.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/db/models.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/exceptions.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/evaluators/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/evaluators/base.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/evaluators/code_evaluators.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/evaluators/llm_evaluators.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/evaluators/utils.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/tracing.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/experiments/utils.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/inferences/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/inferences/errors.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/inferences/fixtures.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/inferences/inferences.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/inferences/schema.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/inferences/validation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/README.md +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/binning.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/metrics.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/mixins.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/retrieval_metrics.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/timeseries.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/metrics/wrappers.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/pointcloud/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/pointcloud/clustering.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/pointcloud/pointcloud.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/pointcloud/projectors.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/pointcloud/umap_parameters.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/py.typed +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/cache/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/dataloaders/cache/two_tier_cache.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/helpers/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/helpers/dataset_helpers.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/AddExamplesToDatasetInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/AddSpansToDatasetInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/ClearProjectInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/ClusterInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/Coordinates.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/CreateDatasetInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/CreateSpanAnnotationInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/CreateTraceAnnotationInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DataQualityMetricInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DatasetExampleInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DatasetSort.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DatasetVersionSort.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DeleteAnnotationsInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DeleteDatasetInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DeleteExperimentsInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DimensionFilter.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/DimensionInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/Granularity.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/PatchAnnotationInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/PatchDatasetExamplesInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/PatchDatasetInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/PerformanceMetricInput.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/SpanSort.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/TimeRange.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/input_types/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/interceptor.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/auth.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/dataset_mutations.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/experiment_mutations.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/export_events_mutations.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/mutations/project_mutations.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/openapi/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/queries.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/routers/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/routers/utils.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/schema.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Annotation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/AnnotatorKind.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Cluster.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/CreateDatasetPayload.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DataQualityMetric.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Dataset.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DatasetExample.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DatasetExampleRevision.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DatasetValues.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DatasetVersion.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Dimension.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DimensionDataType.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DimensionShape.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DimensionType.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DimensionWithValue.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DocumentEvaluationSummary.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/DocumentRetrievalMetrics.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/EmbeddingDimension.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/EmbeddingMetadata.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Evaluation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/EvaluationSummary.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Event.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/EventMetadata.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ExampleRevisionInterface.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Experiment.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ExperimentAnnotationSummary.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ExperimentComparison.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ExperimentRun.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ExperimentRunAnnotation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ExportedFile.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Functionality.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Inferences.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/InferencesRole.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/MimeType.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Model.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/NumericRange.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/PerformanceMetric.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Project.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/PromptResponse.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Retrieval.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ScalarDriftMetricEnum.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/Segments.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/SortDir.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/SpanAnnotation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/TimeSeries.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/TraceAnnotation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/UMAPPoints.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/ValidationResult.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/VectorDriftMetricEnum.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/node.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/api/types/pagination.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/openapi/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/prometheus.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-114x114.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-120x120.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-144x144.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-152x152.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-180x180.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-72x72.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon-76x76.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/apple-touch-icon.png +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/assets/vendor-DxkFTwjz.css +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/assets/vendor-three-DwGkEfCM.js +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/favicon.ico +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/static/modernizr.js +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/telemetry.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/templates/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/server/templates/index.html +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/services.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/session/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/session/data_extractor.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/session/evaluation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/settings.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/attributes.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/dsl/README.md +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/dsl/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/dsl/helpers.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/dsl/query.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/errors.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/evaluation_conventions.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/exporter.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/langchain/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/langchain/instrumentor.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/llama_index/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/llama_index/callback.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/openai/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/openai/instrumentor.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/otel.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/projects.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/schemas.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/span_evaluations.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/span_json_decoder.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/span_json_encoder.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/trace_dataset.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/v1/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/v1/evaluation_pb2.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/trace/v1/evaluation_pb2.pyi +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/__init__.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/deprecation.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/error_handling.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/json.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/logging.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/re.py +0 -0
- {arize_phoenix-4.14.1 → arize_phoenix-4.16.0}/src/phoenix/utilities/span_store.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: arize-phoenix
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.16.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
|
|
@@ -22,6 +22,7 @@ Requires-Dist: aiosqlite
|
|
|
22
22
|
Requires-Dist: alembic<2,>=1.3.0
|
|
23
23
|
Requires-Dist: arize-phoenix-evals>=0.13.1
|
|
24
24
|
Requires-Dist: cachetools
|
|
25
|
+
Requires-Dist: fastapi
|
|
25
26
|
Requires-Dist: grpcio
|
|
26
27
|
Requires-Dist: hdbscan>=0.8.33
|
|
27
28
|
Requires-Dist: httpx
|
|
@@ -40,8 +41,8 @@ Requires-Dist: pandas>=1.0
|
|
|
40
41
|
Requires-Dist: protobuf<6.0,>=3.20
|
|
41
42
|
Requires-Dist: psutil
|
|
42
43
|
Requires-Dist: pyarrow
|
|
44
|
+
Requires-Dist: pydantic!=2.0.*,<3,>=1.0
|
|
43
45
|
Requires-Dist: python-multipart
|
|
44
|
-
Requires-Dist: pyyaml
|
|
45
46
|
Requires-Dist: scikit-learn
|
|
46
47
|
Requires-Dist: scipy
|
|
47
48
|
Requires-Dist: sqlalchemy[asyncio]<3,>=2.0.4
|
|
@@ -56,9 +57,9 @@ Requires-Dist: uvicorn
|
|
|
56
57
|
Requires-Dist: wrapt
|
|
57
58
|
Provides-Extra: container
|
|
58
59
|
Requires-Dist: opentelemetry-exporter-otlp; extra == 'container'
|
|
60
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi; extra == 'container'
|
|
59
61
|
Requires-Dist: opentelemetry-instrumentation-grpc; extra == 'container'
|
|
60
62
|
Requires-Dist: opentelemetry-instrumentation-sqlalchemy; extra == 'container'
|
|
61
|
-
Requires-Dist: opentelemetry-instrumentation-starlette; extra == 'container'
|
|
62
63
|
Requires-Dist: opentelemetry-proto>=1.12.0; extra == 'container'
|
|
63
64
|
Requires-Dist: opentelemetry-sdk; extra == 'container'
|
|
64
65
|
Requires-Dist: opentelemetry-semantic-conventions; extra == 'container'
|
|
@@ -71,6 +72,7 @@ Requires-Dist: anthropic; extra == 'dev'
|
|
|
71
72
|
Requires-Dist: arize[autoembeddings,llm-evaluation]; extra == 'dev'
|
|
72
73
|
Requires-Dist: asgi-lifespan; extra == 'dev'
|
|
73
74
|
Requires-Dist: asyncpg; extra == 'dev'
|
|
75
|
+
Requires-Dist: faker>=26.0.0; extra == 'dev'
|
|
74
76
|
Requires-Dist: gcsfs; extra == 'dev'
|
|
75
77
|
Requires-Dist: google-cloud-aiplatform>=1.3; extra == 'dev'
|
|
76
78
|
Requires-Dist: hatch; extra == 'dev'
|
|
@@ -59,7 +59,8 @@ dependencies = [
|
|
|
59
59
|
"cachetools",
|
|
60
60
|
"python-multipart", # see https://www.starlette.io/#dependencies
|
|
61
61
|
"arize-phoenix-evals>=0.13.1",
|
|
62
|
-
"
|
|
62
|
+
"fastapi",
|
|
63
|
+
"pydantic>=1.0,!=2.0.*,<3,", # exclude 2.0.* since it does not support the `json_encoders` configuration setting
|
|
63
64
|
]
|
|
64
65
|
dynamic = ["version"]
|
|
65
66
|
|
|
@@ -92,6 +93,7 @@ dev = [
|
|
|
92
93
|
"anthropic",
|
|
93
94
|
"prometheus_client",
|
|
94
95
|
"asgi-lifespan",
|
|
96
|
+
"Faker>=26.0.0",
|
|
95
97
|
]
|
|
96
98
|
evals = []
|
|
97
99
|
experimental = []
|
|
@@ -111,7 +113,7 @@ container = [
|
|
|
111
113
|
"opentelemetry-proto>=1.12.0",
|
|
112
114
|
"opentelemetry-exporter-otlp",
|
|
113
115
|
"opentelemetry-semantic-conventions",
|
|
114
|
-
"opentelemetry-instrumentation-
|
|
116
|
+
"opentelemetry-instrumentation-fastapi",
|
|
115
117
|
"opentelemetry-instrumentation-sqlalchemy",
|
|
116
118
|
"opentelemetry-instrumentation-grpc",
|
|
117
119
|
"py-grpc-prometheus",
|
|
@@ -161,13 +163,16 @@ dependencies = [
|
|
|
161
163
|
"protobuf==3.20", # version minimum (for tests)
|
|
162
164
|
"responses",
|
|
163
165
|
"tiktoken",
|
|
164
|
-
"typing-extensions==4.5.0; python_version
|
|
165
|
-
"typing-extensions==4.6.0; python_version
|
|
166
|
+
"typing-extensions==4.5.0; python_version=='3.8'",
|
|
167
|
+
"typing-extensions==4.6.0; python_version=='3.9'",
|
|
168
|
+
"pydantic==1.9.0; python_version<='3.9'", # minimum version of pydantic compatible with openai
|
|
169
|
+
"pydantic==2.8.2; python_version=='3.12'",
|
|
166
170
|
"httpx", # For OpenAI testing
|
|
167
171
|
"respx", # For OpenAI testing
|
|
168
172
|
"nest-asyncio", # for executor testing
|
|
169
173
|
"astunparse; python_version<'3.9'", # `ast.unparse(...)` is only available starting with Python 3.9
|
|
170
174
|
"asgi-lifespan",
|
|
175
|
+
"Faker>=26.0.0",
|
|
171
176
|
]
|
|
172
177
|
|
|
173
178
|
[tool.hatch.envs.type]
|
|
@@ -190,12 +195,15 @@ dependencies = [
|
|
|
190
195
|
"opentelemetry-proto>=1.12.0",
|
|
191
196
|
"opentelemetry-exporter-otlp",
|
|
192
197
|
"opentelemetry-semantic-conventions",
|
|
193
|
-
"opentelemetry-instrumentation-
|
|
198
|
+
"opentelemetry-instrumentation-fastapi",
|
|
194
199
|
"opentelemetry-instrumentation-sqlalchemy",
|
|
195
200
|
"opentelemetry-instrumentation-grpc",
|
|
196
201
|
"py-grpc-prometheus",
|
|
197
202
|
"strawberry-graphql[opentelemetry]==0.236.0", # need to pin version because we're monkey-patching
|
|
198
203
|
"requests", # this is needed to type-check third-party packages
|
|
204
|
+
"pydantic==1.10.17; python_version=='3.8'", # lower minor versions of pydantic break strawberry mypy plugin
|
|
205
|
+
"pydantic==1.10.17; python_version=='3.9'", # lower minor versions of pydantic break strawberry mypy plugin
|
|
206
|
+
"pydantic==2.8.2; python_version=='3.12'",
|
|
199
207
|
]
|
|
200
208
|
|
|
201
209
|
[[tool.hatch.envs.type.matrix]]
|
|
@@ -310,11 +318,12 @@ build = 'strawberry export-schema phoenix.server.api.schema:schema > app/schema.
|
|
|
310
318
|
|
|
311
319
|
[tool.hatch.envs.openapi]
|
|
312
320
|
dependencies = [
|
|
313
|
-
"
|
|
321
|
+
"pydantic==2.8.2",
|
|
322
|
+
"fastapi==0.111.0",
|
|
314
323
|
]
|
|
315
324
|
|
|
316
325
|
[tool.hatch.envs.openapi.scripts]
|
|
317
|
-
build =
|
|
326
|
+
build = "python -m phoenix.server.api.openapi.main > schemas/openapi.json"
|
|
318
327
|
|
|
319
328
|
[tool.hatch.envs.proto]
|
|
320
329
|
detached = true
|
|
@@ -379,6 +388,7 @@ module = [
|
|
|
379
388
|
"sqlean",
|
|
380
389
|
"grpc.*",
|
|
381
390
|
"py_grpc_prometheus.*",
|
|
391
|
+
"orjson", # suppress fastapi internal type errors
|
|
382
392
|
]
|
|
383
393
|
ignore_missing_imports = true
|
|
384
394
|
|
|
@@ -1,28 +1,36 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
|
-
from asyncio import Queue
|
|
3
|
+
from asyncio import Queue, as_completed
|
|
4
|
+
from collections import defaultdict
|
|
4
5
|
from dataclasses import dataclass, field
|
|
5
6
|
from datetime import datetime, timezone
|
|
7
|
+
from functools import singledispatchmethod
|
|
6
8
|
from itertools import islice
|
|
7
9
|
from time import perf_counter
|
|
8
10
|
from typing import (
|
|
9
11
|
Any,
|
|
10
|
-
AsyncContextManager,
|
|
11
12
|
Awaitable,
|
|
12
13
|
Callable,
|
|
14
|
+
DefaultDict,
|
|
15
|
+
Dict,
|
|
13
16
|
Iterable,
|
|
14
17
|
List,
|
|
18
|
+
Mapping,
|
|
15
19
|
Optional,
|
|
16
20
|
Set,
|
|
17
21
|
Tuple,
|
|
22
|
+
Type,
|
|
18
23
|
cast,
|
|
19
24
|
)
|
|
20
25
|
|
|
21
26
|
from cachetools import LRUCache
|
|
22
|
-
from sqlalchemy
|
|
27
|
+
from sqlalchemy import Select, select
|
|
23
28
|
from typing_extensions import TypeAlias
|
|
24
29
|
|
|
25
30
|
import phoenix.trace.v1 as pb
|
|
31
|
+
from phoenix.db import models
|
|
32
|
+
from phoenix.db.insertion.constants import DEFAULT_RETRY_ALLOWANCE, DEFAULT_RETRY_DELAY_SEC
|
|
33
|
+
from phoenix.db.insertion.document_annotation import DocumentAnnotationQueueInserter
|
|
26
34
|
from phoenix.db.insertion.evaluation import (
|
|
27
35
|
EvaluationInsertionEvent,
|
|
28
36
|
InsertEvaluationError,
|
|
@@ -30,7 +38,11 @@ from phoenix.db.insertion.evaluation import (
|
|
|
30
38
|
)
|
|
31
39
|
from phoenix.db.insertion.helpers import DataManipulation, DataManipulationEvent
|
|
32
40
|
from phoenix.db.insertion.span import SpanInsertionEvent, insert_span
|
|
41
|
+
from phoenix.db.insertion.span_annotation import SpanAnnotationQueueInserter
|
|
42
|
+
from phoenix.db.insertion.trace_annotation import TraceAnnotationQueueInserter
|
|
43
|
+
from phoenix.db.insertion.types import Insertables, Precursors
|
|
33
44
|
from phoenix.server.api.dataloaders import CacheForDataLoaders
|
|
45
|
+
from phoenix.server.types import DbSessionFactory
|
|
34
46
|
from phoenix.trace.schemas import Span
|
|
35
47
|
|
|
36
48
|
logger = logging.getLogger(__name__)
|
|
@@ -46,7 +58,7 @@ class TransactionResult:
|
|
|
46
58
|
class BulkInserter:
|
|
47
59
|
def __init__(
|
|
48
60
|
self,
|
|
49
|
-
db:
|
|
61
|
+
db: DbSessionFactory,
|
|
50
62
|
*,
|
|
51
63
|
cache_for_dataloaders: Optional[CacheForDataLoaders] = None,
|
|
52
64
|
initial_batch_of_operations: Iterable[DataManipulation] = (),
|
|
@@ -56,6 +68,8 @@ class BulkInserter:
|
|
|
56
68
|
max_ops_per_transaction: int = 1000,
|
|
57
69
|
max_queue_size: int = 1000,
|
|
58
70
|
enable_prometheus: bool = False,
|
|
71
|
+
retry_delay_sec: float = DEFAULT_RETRY_DELAY_SEC,
|
|
72
|
+
retry_allowance: int = DEFAULT_RETRY_ALLOWANCE,
|
|
59
73
|
) -> None:
|
|
60
74
|
"""
|
|
61
75
|
:param db: A function to initiate a new database session.
|
|
@@ -82,6 +96,9 @@ class BulkInserter:
|
|
|
82
96
|
self._last_updated_at_by_project: LRUCache[ProjectRowId, datetime] = LRUCache(maxsize=100)
|
|
83
97
|
self._cache_for_dataloaders = cache_for_dataloaders
|
|
84
98
|
self._enable_prometheus = enable_prometheus
|
|
99
|
+
self._retry_delay_sec = retry_delay_sec
|
|
100
|
+
self._retry_allowance = retry_allowance
|
|
101
|
+
self._queue_inserters = _QueueInserters(db, self._retry_delay_sec, self._retry_allowance)
|
|
85
102
|
|
|
86
103
|
def last_updated_at(self, project_rowid: Optional[ProjectRowId] = None) -> Optional[datetime]:
|
|
87
104
|
if isinstance(project_rowid, ProjectRowId):
|
|
@@ -91,6 +108,7 @@ class BulkInserter:
|
|
|
91
108
|
async def __aenter__(
|
|
92
109
|
self,
|
|
93
110
|
) -> Tuple[
|
|
111
|
+
Callable[[Any], Awaitable[None]],
|
|
94
112
|
Callable[[Span, str], Awaitable[None]],
|
|
95
113
|
Callable[[pb.Evaluation], Awaitable[None]],
|
|
96
114
|
Callable[[DataManipulation], None],
|
|
@@ -99,6 +117,7 @@ class BulkInserter:
|
|
|
99
117
|
self._operations = Queue(maxsize=self._max_queue_size)
|
|
100
118
|
self._task = asyncio.create_task(self._bulk_insert())
|
|
101
119
|
return (
|
|
120
|
+
self._enqueue,
|
|
102
121
|
self._queue_span,
|
|
103
122
|
self._queue_evaluation,
|
|
104
123
|
self._enqueue_operation,
|
|
@@ -110,6 +129,9 @@ class BulkInserter:
|
|
|
110
129
|
self._task.cancel()
|
|
111
130
|
self._task = None
|
|
112
131
|
|
|
132
|
+
async def _enqueue(self, *items: Any) -> None:
|
|
133
|
+
await self._queue_inserters.enqueue(*items)
|
|
134
|
+
|
|
113
135
|
def _enqueue_operation(self, operation: DataManipulation) -> None:
|
|
114
136
|
cast("Queue[DataManipulation]", self._operations).put_nowait(operation)
|
|
115
137
|
|
|
@@ -125,7 +147,17 @@ class BulkInserter:
|
|
|
125
147
|
assert isinstance(self._operations, Queue)
|
|
126
148
|
spans_buffer, evaluations_buffer = None, None
|
|
127
149
|
# start first insert immediately if the inserter has not run recently
|
|
128
|
-
while
|
|
150
|
+
while (
|
|
151
|
+
self._running
|
|
152
|
+
or not self._queue_inserters.empty
|
|
153
|
+
or not self._operations.empty()
|
|
154
|
+
or self._spans
|
|
155
|
+
or self._evaluations
|
|
156
|
+
):
|
|
157
|
+
if not self._queue_inserters.empty:
|
|
158
|
+
if inserted_ids := await self._queue_inserters.insert():
|
|
159
|
+
for project_rowid in await self._get_project_rowids(inserted_ids):
|
|
160
|
+
self._last_updated_at_by_project[project_rowid] = datetime.now(timezone.utc)
|
|
129
161
|
if self._operations.empty() and not (self._spans or self._evaluations):
|
|
130
162
|
await asyncio.sleep(self._sleep)
|
|
131
163
|
continue
|
|
@@ -245,3 +277,97 @@ class BulkInserter:
|
|
|
245
277
|
BULK_LOADER_EXCEPTIONS.inc()
|
|
246
278
|
logger.exception("Failed to insert evaluations")
|
|
247
279
|
return transaction_result
|
|
280
|
+
|
|
281
|
+
async def _get_project_rowids(
|
|
282
|
+
self,
|
|
283
|
+
inserted_ids: Mapping[Type[models.Base], List[int]],
|
|
284
|
+
) -> Set[int]:
|
|
285
|
+
ans: Set[int] = set()
|
|
286
|
+
if not inserted_ids:
|
|
287
|
+
return ans
|
|
288
|
+
stmt: Select[Tuple[int]]
|
|
289
|
+
for table, ids in inserted_ids.items():
|
|
290
|
+
if not ids:
|
|
291
|
+
continue
|
|
292
|
+
if issubclass(table, models.SpanAnnotation):
|
|
293
|
+
stmt = (
|
|
294
|
+
select(models.Project.id)
|
|
295
|
+
.join(models.Trace)
|
|
296
|
+
.join_from(models.Trace, models.Span)
|
|
297
|
+
.join_from(models.Span, models.SpanAnnotation)
|
|
298
|
+
.where(models.SpanAnnotation.id.in_(ids))
|
|
299
|
+
)
|
|
300
|
+
elif issubclass(table, models.DocumentAnnotation):
|
|
301
|
+
stmt = (
|
|
302
|
+
select(models.Project.id)
|
|
303
|
+
.join(models.Trace)
|
|
304
|
+
.join_from(models.Trace, models.Span)
|
|
305
|
+
.join_from(models.Span, models.DocumentAnnotation)
|
|
306
|
+
.where(models.DocumentAnnotation.id.in_(ids))
|
|
307
|
+
)
|
|
308
|
+
elif issubclass(table, models.TraceAnnotation):
|
|
309
|
+
stmt = (
|
|
310
|
+
select(models.Project.id)
|
|
311
|
+
.join(models.Trace)
|
|
312
|
+
.join_from(models.Trace, models.TraceAnnotation)
|
|
313
|
+
.where(models.TraceAnnotation.id.in_(ids))
|
|
314
|
+
)
|
|
315
|
+
else:
|
|
316
|
+
continue
|
|
317
|
+
async with self._db() as session:
|
|
318
|
+
project_rowids = [_ async for _ in await session.stream_scalars(stmt)]
|
|
319
|
+
ans.update(project_rowids)
|
|
320
|
+
return ans
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class _QueueInserters:
|
|
324
|
+
def __init__(
|
|
325
|
+
self,
|
|
326
|
+
db: DbSessionFactory,
|
|
327
|
+
retry_delay_sec: float = DEFAULT_RETRY_DELAY_SEC,
|
|
328
|
+
retry_allowance: int = DEFAULT_RETRY_ALLOWANCE,
|
|
329
|
+
) -> None:
|
|
330
|
+
self._db = db
|
|
331
|
+
args = (db, retry_delay_sec, retry_allowance)
|
|
332
|
+
self._span_annotations = SpanAnnotationQueueInserter(*args)
|
|
333
|
+
self._trace_annotations = TraceAnnotationQueueInserter(*args)
|
|
334
|
+
self._document_annotations = DocumentAnnotationQueueInserter(*args)
|
|
335
|
+
self._queues = (
|
|
336
|
+
self._span_annotations,
|
|
337
|
+
self._trace_annotations,
|
|
338
|
+
self._document_annotations,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
async def insert(self) -> Dict[Type[models.Base], List[int]]:
|
|
342
|
+
ans: DefaultDict[Type[models.Base], List[int]] = defaultdict(list)
|
|
343
|
+
for coro in as_completed([q.insert() for q in self._queues]):
|
|
344
|
+
table, inserted_ids = await coro
|
|
345
|
+
if inserted_ids:
|
|
346
|
+
ans[table].extend(inserted_ids)
|
|
347
|
+
return ans
|
|
348
|
+
|
|
349
|
+
@property
|
|
350
|
+
def empty(self) -> bool:
|
|
351
|
+
return all(q.empty for q in self._queues)
|
|
352
|
+
|
|
353
|
+
async def enqueue(self, *items: Any) -> None:
|
|
354
|
+
for item in items:
|
|
355
|
+
await self._enqueue(item)
|
|
356
|
+
|
|
357
|
+
@singledispatchmethod
|
|
358
|
+
async def _enqueue(self, item: Any) -> None: ...
|
|
359
|
+
|
|
360
|
+
@_enqueue.register(Precursors.SpanAnnotation)
|
|
361
|
+
@_enqueue.register(Insertables.SpanAnnotation)
|
|
362
|
+
async def _(self, item: Precursors.SpanAnnotation) -> None:
|
|
363
|
+
await self._span_annotations.enqueue(item)
|
|
364
|
+
|
|
365
|
+
@_enqueue.register(Precursors.TraceAnnotation)
|
|
366
|
+
@_enqueue.register(Insertables.TraceAnnotation)
|
|
367
|
+
async def _(self, item: Precursors.TraceAnnotation) -> None:
|
|
368
|
+
await self._trace_annotations.enqueue(item)
|
|
369
|
+
|
|
370
|
+
@_enqueue.register(Precursors.DocumentAnnotation)
|
|
371
|
+
@_enqueue.register(Insertables.DocumentAnnotation)
|
|
372
|
+
async def _(self, item: Precursors.DocumentAnnotation) -> None:
|
|
373
|
+
await self._document_annotations.enqueue(item)
|
|
@@ -8,7 +8,7 @@ from typing import Any
|
|
|
8
8
|
import aiosqlite
|
|
9
9
|
import numpy as np
|
|
10
10
|
import sqlean
|
|
11
|
-
from sqlalchemy import URL, event, make_url
|
|
11
|
+
from sqlalchemy import URL, StaticPool, event, make_url
|
|
12
12
|
from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
13
13
|
from typing_extensions import assert_never
|
|
14
14
|
|
|
@@ -105,6 +105,7 @@ def aio_sqlite_engine(
|
|
|
105
105
|
echo=echo,
|
|
106
106
|
json_serializer=_dumps,
|
|
107
107
|
async_creator=async_creator,
|
|
108
|
+
poolclass=StaticPool,
|
|
108
109
|
)
|
|
109
110
|
event.listen(engine.sync_engine, "connect", set_sqlite_pragma)
|
|
110
111
|
if not migrate:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import Any, Optional, Tuple
|
|
2
|
+
from typing import Any, Callable, Hashable, Iterable, List, Optional, Set, Tuple, TypeVar
|
|
3
3
|
|
|
4
4
|
from openinference.semconv.trace import (
|
|
5
5
|
OpenInferenceSpanKindValues,
|
|
@@ -80,3 +80,25 @@ def get_project_names_for_experiments(*experiment_ids: int) -> Select[Tuple[Opti
|
|
|
80
80
|
.where(models.Experiment.id.in_(set(experiment_ids)))
|
|
81
81
|
.where(models.Experiment.project_name.isnot(None))
|
|
82
82
|
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
_AnyT = TypeVar("_AnyT")
|
|
86
|
+
_KeyT = TypeVar("_KeyT", bound=Hashable)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def dedup(
|
|
90
|
+
items: Iterable[_AnyT],
|
|
91
|
+
key: Callable[[_AnyT], _KeyT],
|
|
92
|
+
) -> List[_AnyT]:
|
|
93
|
+
"""
|
|
94
|
+
Discard subsequent duplicates after the first appearance in `items`.
|
|
95
|
+
"""
|
|
96
|
+
ans = []
|
|
97
|
+
seen: Set[_KeyT] = set()
|
|
98
|
+
for item in items:
|
|
99
|
+
if (k := key(item)) in seen:
|
|
100
|
+
continue
|
|
101
|
+
else:
|
|
102
|
+
ans.append(item)
|
|
103
|
+
seen.add(k)
|
|
104
|
+
return ans
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, List, Mapping, NamedTuple, Optional, Tuple
|
|
3
|
+
|
|
4
|
+
from sqlalchemy import Row, Select, and_, select, tuple_
|
|
5
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
6
|
+
from typing_extensions import TypeAlias
|
|
7
|
+
|
|
8
|
+
from phoenix.db import models
|
|
9
|
+
from phoenix.db.helpers import dedup, num_docs_col
|
|
10
|
+
from phoenix.db.insertion.types import (
|
|
11
|
+
Insertables,
|
|
12
|
+
Postponed,
|
|
13
|
+
Precursors,
|
|
14
|
+
QueueInserter,
|
|
15
|
+
Received,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
_Name: TypeAlias = str
|
|
19
|
+
_SpanId: TypeAlias = str
|
|
20
|
+
_SpanRowId: TypeAlias = int
|
|
21
|
+
_DocumentPosition: TypeAlias = int
|
|
22
|
+
_AnnoRowId: TypeAlias = int
|
|
23
|
+
_NumDocs: TypeAlias = int
|
|
24
|
+
|
|
25
|
+
_Key: TypeAlias = Tuple[_Name, _SpanId, _DocumentPosition]
|
|
26
|
+
_UniqueBy: TypeAlias = Tuple[_Name, _SpanRowId, _DocumentPosition]
|
|
27
|
+
_Existing: TypeAlias = Tuple[
|
|
28
|
+
_SpanRowId,
|
|
29
|
+
_SpanId,
|
|
30
|
+
_NumDocs,
|
|
31
|
+
Optional[_AnnoRowId],
|
|
32
|
+
Optional[_Name],
|
|
33
|
+
Optional[_DocumentPosition],
|
|
34
|
+
Optional[datetime],
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DocumentAnnotationQueueInserter(
|
|
39
|
+
QueueInserter[
|
|
40
|
+
Precursors.DocumentAnnotation,
|
|
41
|
+
Insertables.DocumentAnnotation,
|
|
42
|
+
models.DocumentAnnotation,
|
|
43
|
+
],
|
|
44
|
+
table=models.DocumentAnnotation,
|
|
45
|
+
unique_by=("name", "span_rowid", "document_position"),
|
|
46
|
+
):
|
|
47
|
+
async def _partition(
|
|
48
|
+
self,
|
|
49
|
+
session: AsyncSession,
|
|
50
|
+
*parcels: Received[Precursors.DocumentAnnotation],
|
|
51
|
+
) -> Tuple[
|
|
52
|
+
List[Received[Insertables.DocumentAnnotation]],
|
|
53
|
+
List[Postponed[Precursors.DocumentAnnotation]],
|
|
54
|
+
List[Received[Precursors.DocumentAnnotation]],
|
|
55
|
+
]:
|
|
56
|
+
to_insert: List[Received[Insertables.DocumentAnnotation]] = []
|
|
57
|
+
to_postpone: List[Postponed[Precursors.DocumentAnnotation]] = []
|
|
58
|
+
to_discard: List[Received[Precursors.DocumentAnnotation]] = []
|
|
59
|
+
|
|
60
|
+
stmt = self._select_existing(*map(_key, parcels))
|
|
61
|
+
existing: List[Row[_Existing]] = [_ async for _ in await session.stream(stmt)]
|
|
62
|
+
existing_spans: Mapping[str, _SpanAttr] = {
|
|
63
|
+
e.span_id: _SpanAttr(e.span_rowid, e.num_docs) for e in existing
|
|
64
|
+
}
|
|
65
|
+
existing_annos: Mapping[_Key, _AnnoAttr] = {
|
|
66
|
+
(e.name, e.span_id, e.document_position): _AnnoAttr(e.span_rowid, e.id, e.updated_at)
|
|
67
|
+
for e in existing
|
|
68
|
+
if e.id is not None
|
|
69
|
+
and e.name is not None
|
|
70
|
+
and e.document_position is not None
|
|
71
|
+
and e.updated_at is not None
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for p in parcels:
|
|
75
|
+
if (anno := existing_annos.get(_key(p))) is not None:
|
|
76
|
+
if p.received_at <= anno.updated_at:
|
|
77
|
+
to_discard.append(p)
|
|
78
|
+
else:
|
|
79
|
+
to_insert.append(
|
|
80
|
+
Received(
|
|
81
|
+
received_at=p.received_at,
|
|
82
|
+
item=p.item.as_insertable(
|
|
83
|
+
span_rowid=anno.span_rowid,
|
|
84
|
+
id_=anno.id_,
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
elif (span := existing_spans.get(p.item.span_id)) is not None:
|
|
89
|
+
if 0 <= p.item.document_position < span.num_docs:
|
|
90
|
+
to_insert.append(
|
|
91
|
+
Received(
|
|
92
|
+
received_at=p.received_at,
|
|
93
|
+
item=p.item.as_insertable(
|
|
94
|
+
span_rowid=span.span_rowid,
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
else:
|
|
99
|
+
to_discard.append(p)
|
|
100
|
+
elif isinstance(p, Postponed):
|
|
101
|
+
if p.retries_left > 1:
|
|
102
|
+
to_postpone.append(p.postpone(p.retries_left - 1))
|
|
103
|
+
else:
|
|
104
|
+
to_discard.append(p)
|
|
105
|
+
elif isinstance(p, Received):
|
|
106
|
+
to_postpone.append(p.postpone(self._retry_allowance))
|
|
107
|
+
else:
|
|
108
|
+
to_discard.append(p)
|
|
109
|
+
|
|
110
|
+
assert len(to_insert) + len(to_postpone) + len(to_discard) == len(parcels)
|
|
111
|
+
to_insert = dedup(sorted(to_insert, key=_time, reverse=True), _unique_by)[::-1]
|
|
112
|
+
return to_insert, to_postpone, to_discard
|
|
113
|
+
|
|
114
|
+
def _select_existing(self, *keys: _Key) -> Select[_Existing]:
|
|
115
|
+
anno = self.table
|
|
116
|
+
span = (
|
|
117
|
+
select(models.Span.id, models.Span.span_id, num_docs_col(self._db.dialect))
|
|
118
|
+
.where(models.Span.span_id.in_({span_id for _, span_id, *_ in keys}))
|
|
119
|
+
.cte()
|
|
120
|
+
)
|
|
121
|
+
onclause = and_(
|
|
122
|
+
span.c.id == anno.span_rowid,
|
|
123
|
+
anno.name.in_({name for name, *_ in keys}),
|
|
124
|
+
tuple_(anno.name, span.c.span_id, anno.document_position).in_(keys),
|
|
125
|
+
)
|
|
126
|
+
return select(
|
|
127
|
+
span.c.id.label("span_rowid"),
|
|
128
|
+
span.c.span_id,
|
|
129
|
+
span.c.num_docs,
|
|
130
|
+
anno.id,
|
|
131
|
+
anno.name,
|
|
132
|
+
anno.document_position,
|
|
133
|
+
anno.updated_at,
|
|
134
|
+
).outerjoin_from(span, anno, onclause)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class _SpanAttr(NamedTuple):
|
|
138
|
+
span_rowid: _SpanRowId
|
|
139
|
+
num_docs: _NumDocs
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class _AnnoAttr(NamedTuple):
|
|
143
|
+
span_rowid: _SpanRowId
|
|
144
|
+
id_: _AnnoRowId
|
|
145
|
+
updated_at: datetime
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _key(p: Received[Precursors.DocumentAnnotation]) -> _Key:
|
|
149
|
+
return p.item.obj.name, p.item.span_id, p.item.document_position
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _unique_by(p: Received[Insertables.DocumentAnnotation]) -> _UniqueBy:
|
|
153
|
+
return p.item.obj.name, p.item.span_rowid, p.item.document_position
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _time(p: Received[Any]) -> datetime:
|
|
157
|
+
return p.received_at
|
|
@@ -20,6 +20,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
20
20
|
from sqlalchemy.sql.elements import KeyedColumnElement
|
|
21
21
|
from typing_extensions import TypeAlias, assert_never
|
|
22
22
|
|
|
23
|
+
from phoenix.db import models
|
|
23
24
|
from phoenix.db.helpers import SupportedSQLDialect
|
|
24
25
|
from phoenix.db.models import Base
|
|
25
26
|
|
|
@@ -93,3 +94,15 @@ def _clean(
|
|
|
93
94
|
yield "metadata", v
|
|
94
95
|
else:
|
|
95
96
|
yield k, v
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def as_kv(obj: models.Base) -> Iterator[Tuple[str, Any]]:
|
|
100
|
+
for k, c in obj.__table__.c.items():
|
|
101
|
+
if k in ["created_at", "updated_at"]:
|
|
102
|
+
continue
|
|
103
|
+
k = "metadata_" if k == "metadata" else k
|
|
104
|
+
v = getattr(obj, k, None)
|
|
105
|
+
if c.primary_key and v is None:
|
|
106
|
+
# postgresql disallows None for primary key
|
|
107
|
+
continue
|
|
108
|
+
yield k, v
|