arize-phoenix 4.4.2__py3-none-any.whl → 4.4.4rc0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. {arize_phoenix-4.4.2.dist-info → arize_phoenix-4.4.4rc0.dist-info}/METADATA +12 -11
  2. {arize_phoenix-4.4.2.dist-info → arize_phoenix-4.4.4rc0.dist-info}/RECORD +110 -57
  3. phoenix/__init__.py +0 -27
  4. phoenix/config.py +21 -7
  5. phoenix/core/model.py +25 -25
  6. phoenix/core/model_schema.py +66 -64
  7. phoenix/core/model_schema_adapter.py +27 -25
  8. phoenix/datasets/__init__.py +0 -0
  9. phoenix/datasets/evaluators.py +275 -0
  10. phoenix/datasets/experiments.py +469 -0
  11. phoenix/datasets/tracing.py +66 -0
  12. phoenix/datasets/types.py +212 -0
  13. phoenix/db/bulk_inserter.py +54 -14
  14. phoenix/db/insertion/dataset.py +234 -0
  15. phoenix/db/insertion/evaluation.py +6 -6
  16. phoenix/db/insertion/helpers.py +13 -2
  17. phoenix/db/migrations/types.py +29 -0
  18. phoenix/db/migrations/versions/10460e46d750_datasets.py +291 -0
  19. phoenix/db/migrations/versions/cf03bd6bae1d_init.py +2 -28
  20. phoenix/db/models.py +230 -3
  21. phoenix/inferences/fixtures.py +23 -23
  22. phoenix/inferences/inferences.py +7 -7
  23. phoenix/inferences/validation.py +1 -1
  24. phoenix/metrics/binning.py +2 -2
  25. phoenix/server/api/context.py +16 -0
  26. phoenix/server/api/dataloaders/__init__.py +16 -0
  27. phoenix/server/api/dataloaders/dataset_example_revisions.py +100 -0
  28. phoenix/server/api/dataloaders/dataset_example_spans.py +43 -0
  29. phoenix/server/api/dataloaders/experiment_annotation_summaries.py +85 -0
  30. phoenix/server/api/dataloaders/experiment_error_rates.py +43 -0
  31. phoenix/server/api/dataloaders/experiment_sequence_number.py +49 -0
  32. phoenix/server/api/dataloaders/project_by_name.py +31 -0
  33. phoenix/server/api/dataloaders/span_descendants.py +2 -3
  34. phoenix/server/api/dataloaders/span_projects.py +33 -0
  35. phoenix/server/api/dataloaders/trace_row_ids.py +39 -0
  36. phoenix/server/api/helpers/dataset_helpers.py +178 -0
  37. phoenix/server/api/input_types/AddExamplesToDatasetInput.py +16 -0
  38. phoenix/server/api/input_types/AddSpansToDatasetInput.py +14 -0
  39. phoenix/server/api/input_types/CreateDatasetInput.py +12 -0
  40. phoenix/server/api/input_types/DatasetExampleInput.py +14 -0
  41. phoenix/server/api/input_types/DatasetSort.py +17 -0
  42. phoenix/server/api/input_types/DatasetVersionSort.py +16 -0
  43. phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +13 -0
  44. phoenix/server/api/input_types/DeleteDatasetInput.py +7 -0
  45. phoenix/server/api/input_types/DeleteExperimentsInput.py +9 -0
  46. phoenix/server/api/input_types/PatchDatasetExamplesInput.py +35 -0
  47. phoenix/server/api/input_types/PatchDatasetInput.py +14 -0
  48. phoenix/server/api/mutations/__init__.py +13 -0
  49. phoenix/server/api/mutations/auth.py +11 -0
  50. phoenix/server/api/mutations/dataset_mutations.py +520 -0
  51. phoenix/server/api/mutations/experiment_mutations.py +65 -0
  52. phoenix/server/api/{types/ExportEventsMutation.py → mutations/export_events_mutations.py} +17 -14
  53. phoenix/server/api/mutations/project_mutations.py +42 -0
  54. phoenix/server/api/queries.py +503 -0
  55. phoenix/server/api/routers/v1/__init__.py +77 -2
  56. phoenix/server/api/routers/v1/dataset_examples.py +178 -0
  57. phoenix/server/api/routers/v1/datasets.py +861 -0
  58. phoenix/server/api/routers/v1/evaluations.py +4 -2
  59. phoenix/server/api/routers/v1/experiment_evaluations.py +65 -0
  60. phoenix/server/api/routers/v1/experiment_runs.py +108 -0
  61. phoenix/server/api/routers/v1/experiments.py +174 -0
  62. phoenix/server/api/routers/v1/spans.py +3 -1
  63. phoenix/server/api/routers/v1/traces.py +1 -4
  64. phoenix/server/api/schema.py +2 -303
  65. phoenix/server/api/types/AnnotatorKind.py +10 -0
  66. phoenix/server/api/types/Cluster.py +19 -19
  67. phoenix/server/api/types/CreateDatasetPayload.py +8 -0
  68. phoenix/server/api/types/Dataset.py +282 -63
  69. phoenix/server/api/types/DatasetExample.py +85 -0
  70. phoenix/server/api/types/DatasetExampleRevision.py +34 -0
  71. phoenix/server/api/types/DatasetVersion.py +14 -0
  72. phoenix/server/api/types/Dimension.py +30 -29
  73. phoenix/server/api/types/EmbeddingDimension.py +40 -34
  74. phoenix/server/api/types/Event.py +16 -16
  75. phoenix/server/api/types/ExampleRevisionInterface.py +14 -0
  76. phoenix/server/api/types/Experiment.py +135 -0
  77. phoenix/server/api/types/ExperimentAnnotationSummary.py +13 -0
  78. phoenix/server/api/types/ExperimentComparison.py +19 -0
  79. phoenix/server/api/types/ExperimentRun.py +91 -0
  80. phoenix/server/api/types/ExperimentRunAnnotation.py +57 -0
  81. phoenix/server/api/types/Inferences.py +80 -0
  82. phoenix/server/api/types/InferencesRole.py +23 -0
  83. phoenix/server/api/types/Model.py +43 -42
  84. phoenix/server/api/types/Project.py +26 -12
  85. phoenix/server/api/types/Segments.py +1 -1
  86. phoenix/server/api/types/Span.py +78 -2
  87. phoenix/server/api/types/TimeSeries.py +6 -6
  88. phoenix/server/api/types/Trace.py +15 -4
  89. phoenix/server/api/types/UMAPPoints.py +1 -1
  90. phoenix/server/api/types/node.py +5 -111
  91. phoenix/server/api/types/pagination.py +10 -52
  92. phoenix/server/app.py +99 -49
  93. phoenix/server/main.py +49 -27
  94. phoenix/server/openapi/docs.py +3 -0
  95. phoenix/server/static/index.js +2246 -1368
  96. phoenix/server/templates/index.html +1 -0
  97. phoenix/services.py +15 -15
  98. phoenix/session/client.py +316 -21
  99. phoenix/session/session.py +47 -37
  100. phoenix/trace/exporter.py +14 -9
  101. phoenix/trace/fixtures.py +133 -7
  102. phoenix/trace/span_evaluations.py +3 -3
  103. phoenix/trace/trace_dataset.py +6 -6
  104. phoenix/utilities/json.py +61 -0
  105. phoenix/utilities/re.py +50 -0
  106. phoenix/version.py +1 -1
  107. phoenix/server/api/types/DatasetRole.py +0 -23
  108. {arize_phoenix-4.4.2.dist-info → arize_phoenix-4.4.4rc0.dist-info}/WHEEL +0 -0
  109. {arize_phoenix-4.4.2.dist-info → arize_phoenix-4.4.4rc0.dist-info}/licenses/IP_NOTICE +0 -0
  110. {arize_phoenix-4.4.2.dist-info → arize_phoenix-4.4.4rc0.dist-info}/licenses/LICENSE +0 -0
  111. /phoenix/server/api/{helpers.py → helpers/__init__.py} +0 -0
@@ -0,0 +1,178 @@
1
+ from sqlalchemy import and_, func, select
2
+ from starlette.requests import Request
3
+ from starlette.responses import JSONResponse, Response
4
+ from starlette.status import HTTP_404_NOT_FOUND
5
+ from strawberry.relay import GlobalID
6
+
7
+ from phoenix.db.models import Dataset, DatasetExample, DatasetExampleRevision, DatasetVersion
8
+
9
+
10
+ async def list_dataset_examples(request: Request) -> Response:
11
+ """
12
+ summary: Get dataset examples by dataset ID
13
+ operationId: getDatasetExamples
14
+ tags:
15
+ - datasets
16
+ parameters:
17
+ - in: path
18
+ name: id
19
+ required: true
20
+ schema:
21
+ type: string
22
+ description: Dataset ID
23
+ - in: query
24
+ name: version-id
25
+ schema:
26
+ type: string
27
+ description: Dataset version ID. If omitted, returns the latest version.
28
+ responses:
29
+ 200:
30
+ description: Success
31
+ content:
32
+ application/json:
33
+ schema:
34
+ type: object
35
+ properties:
36
+ data:
37
+ type: object
38
+ properties:
39
+ dataset_id:
40
+ type: string
41
+ description: ID of the dataset
42
+ version_id:
43
+ type: string
44
+ description: ID of the version
45
+ examples:
46
+ type: array
47
+ items:
48
+ type: object
49
+ properties:
50
+ id:
51
+ type: string
52
+ description: ID of the dataset example
53
+ input:
54
+ type: object
55
+ description: Input data of the example
56
+ output:
57
+ type: object
58
+ description: Output data of the example
59
+ metadata:
60
+ type: object
61
+ description: Metadata of the example
62
+ updated_at:
63
+ type: string
64
+ format: date-time
65
+ description: ISO formatted timestamp of when the example was updated
66
+ required:
67
+ - id
68
+ - input
69
+ - output
70
+ - metadata
71
+ - updated_at
72
+ required:
73
+ - dataset_id
74
+ - version_id
75
+ - examples
76
+ 403:
77
+ description: Forbidden
78
+ 404:
79
+ description: Dataset does not exist.
80
+ """
81
+ dataset_id = GlobalID.from_id(request.path_params["id"])
82
+ raw_version_id = request.query_params.get("version-id")
83
+ version_id = GlobalID.from_id(raw_version_id) if raw_version_id else None
84
+
85
+ if (dataset_type := dataset_id.type_name) != "Dataset":
86
+ return Response(
87
+ content=f"ID {dataset_id} refers to a {dataset_type}", status_code=HTTP_404_NOT_FOUND
88
+ )
89
+
90
+ if version_id and (version_type := version_id.type_name) != "DatasetVersion":
91
+ return Response(
92
+ content=f"ID {version_id} refers to a {version_type}", status_code=HTTP_404_NOT_FOUND
93
+ )
94
+
95
+ async with request.app.state.db() as session:
96
+ if (
97
+ resolved_dataset_id := await session.scalar(
98
+ select(Dataset.id).where(Dataset.id == int(dataset_id.node_id))
99
+ )
100
+ ) is None:
101
+ return Response(
102
+ content=f"No dataset with id {dataset_id} can be found.",
103
+ status_code=HTTP_404_NOT_FOUND,
104
+ )
105
+
106
+ # Subquery to find the maximum created_at for each dataset_example_id
107
+ # timestamp tiebreaks are resolved by the largest id
108
+ partial_subquery = select(
109
+ func.max(DatasetExampleRevision.id).label("max_id"),
110
+ ).group_by(DatasetExampleRevision.dataset_example_id)
111
+
112
+ if version_id:
113
+ if (
114
+ resolved_version_id := await session.scalar(
115
+ select(DatasetVersion.id).where(
116
+ and_(
117
+ DatasetVersion.dataset_id == resolved_dataset_id,
118
+ DatasetVersion.id == int(version_id.node_id),
119
+ )
120
+ )
121
+ )
122
+ ) is None:
123
+ return Response(
124
+ content=f"No dataset version with id {version_id} can be found.",
125
+ status_code=HTTP_404_NOT_FOUND,
126
+ )
127
+ # if a version_id is provided, filter the subquery to only include revisions from that
128
+ partial_subquery = partial_subquery.filter(
129
+ DatasetExampleRevision.dataset_version_id <= resolved_version_id
130
+ )
131
+ else:
132
+ if (
133
+ resolved_version_id := await session.scalar(
134
+ select(func.max(DatasetVersion.id)).where(
135
+ DatasetVersion.dataset_id == resolved_dataset_id
136
+ )
137
+ )
138
+ ) is None:
139
+ return Response(
140
+ content="Dataset has no versions.",
141
+ status_code=HTTP_404_NOT_FOUND,
142
+ )
143
+
144
+ subquery = partial_subquery.subquery()
145
+ # Query for the most recent example revisions that are not deleted
146
+ query = (
147
+ select(DatasetExample, DatasetExampleRevision)
148
+ .join(
149
+ DatasetExampleRevision,
150
+ DatasetExample.id == DatasetExampleRevision.dataset_example_id,
151
+ )
152
+ .join(
153
+ subquery,
154
+ (subquery.c.max_id == DatasetExampleRevision.id),
155
+ )
156
+ .filter(DatasetExample.dataset_id == resolved_dataset_id)
157
+ .filter(DatasetExampleRevision.revision_kind != "DELETE")
158
+ .order_by(DatasetExample.id.asc())
159
+ )
160
+ examples = [
161
+ {
162
+ "id": str(GlobalID("DatasetExample", str(example.id))),
163
+ "input": revision.input,
164
+ "output": revision.output,
165
+ "metadata": revision.metadata_,
166
+ "updated_at": revision.created_at.isoformat(),
167
+ }
168
+ async for example, revision in await session.stream(query)
169
+ ]
170
+ return JSONResponse(
171
+ {
172
+ "data": {
173
+ "dataset_id": str(GlobalID("Dataset", str(resolved_dataset_id))),
174
+ "version_id": str(GlobalID("DatasetVersion", str(resolved_version_id))),
175
+ "examples": examples,
176
+ }
177
+ }
178
+ )