arize-phoenix 4.14.1__py3-none-any.whl → 4.16.0__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.
Potentially problematic release.
This version of arize-phoenix might be problematic. Click here for more details.
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/METADATA +5 -3
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/RECORD +81 -71
- phoenix/db/bulk_inserter.py +131 -5
- phoenix/db/engines.py +2 -1
- phoenix/db/helpers.py +23 -1
- phoenix/db/insertion/constants.py +2 -0
- phoenix/db/insertion/document_annotation.py +157 -0
- phoenix/db/insertion/helpers.py +13 -0
- phoenix/db/insertion/span_annotation.py +144 -0
- phoenix/db/insertion/trace_annotation.py +144 -0
- phoenix/db/insertion/types.py +261 -0
- phoenix/experiments/functions.py +3 -2
- phoenix/experiments/types.py +3 -3
- phoenix/server/api/context.py +7 -9
- phoenix/server/api/dataloaders/__init__.py +2 -0
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +3 -3
- phoenix/server/api/dataloaders/dataset_example_revisions.py +2 -4
- phoenix/server/api/dataloaders/dataset_example_spans.py +2 -4
- phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -4
- phoenix/server/api/dataloaders/document_evaluations.py +2 -4
- phoenix/server/api/dataloaders/document_retrieval_metrics.py +2 -4
- phoenix/server/api/dataloaders/evaluation_summaries.py +2 -4
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +2 -4
- phoenix/server/api/dataloaders/experiment_error_rates.py +2 -4
- phoenix/server/api/dataloaders/experiment_run_counts.py +2 -4
- phoenix/server/api/dataloaders/experiment_sequence_number.py +2 -4
- phoenix/server/api/dataloaders/latency_ms_quantile.py +2 -3
- phoenix/server/api/dataloaders/min_start_or_max_end_times.py +2 -4
- phoenix/server/api/dataloaders/project_by_name.py +3 -3
- phoenix/server/api/dataloaders/record_counts.py +2 -4
- phoenix/server/api/dataloaders/span_annotations.py +2 -4
- phoenix/server/api/dataloaders/span_dataset_examples.py +36 -0
- phoenix/server/api/dataloaders/span_descendants.py +2 -4
- phoenix/server/api/dataloaders/span_evaluations.py +2 -4
- phoenix/server/api/dataloaders/span_projects.py +3 -3
- phoenix/server/api/dataloaders/token_counts.py +2 -4
- phoenix/server/api/dataloaders/trace_evaluations.py +2 -4
- phoenix/server/api/dataloaders/trace_row_ids.py +2 -4
- phoenix/server/api/input_types/SpanAnnotationSort.py +17 -0
- phoenix/server/api/input_types/TraceAnnotationSort.py +17 -0
- phoenix/server/api/mutations/span_annotations_mutations.py +8 -3
- phoenix/server/api/mutations/trace_annotations_mutations.py +8 -3
- phoenix/server/api/openapi/main.py +18 -2
- phoenix/server/api/openapi/schema.py +12 -12
- phoenix/server/api/routers/v1/__init__.py +36 -83
- phoenix/server/api/routers/v1/datasets.py +515 -509
- phoenix/server/api/routers/v1/evaluations.py +164 -73
- phoenix/server/api/routers/v1/experiment_evaluations.py +68 -91
- phoenix/server/api/routers/v1/experiment_runs.py +98 -155
- phoenix/server/api/routers/v1/experiments.py +132 -181
- phoenix/server/api/routers/v1/pydantic_compat.py +78 -0
- phoenix/server/api/routers/v1/spans.py +164 -203
- phoenix/server/api/routers/v1/traces.py +134 -159
- phoenix/server/api/routers/v1/utils.py +95 -0
- phoenix/server/api/types/Span.py +27 -3
- phoenix/server/api/types/Trace.py +21 -4
- phoenix/server/api/utils.py +4 -4
- phoenix/server/app.py +172 -192
- phoenix/server/grpc_server.py +2 -2
- phoenix/server/main.py +5 -9
- phoenix/server/static/.vite/manifest.json +31 -31
- phoenix/server/static/assets/components-Ci5kMOk5.js +1175 -0
- phoenix/server/static/assets/{index-CQgXRwU0.js → index-BQG5WVX7.js} +2 -2
- phoenix/server/static/assets/{pages-hdjlFZhO.js → pages-BrevprVW.js} +451 -275
- phoenix/server/static/assets/{vendor-DPvSDRn3.js → vendor-CP0b0YG0.js} +2 -2
- phoenix/server/static/assets/{vendor-arizeai-CkvPT67c.js → vendor-arizeai-DTbiPGp6.js} +27 -27
- phoenix/server/static/assets/vendor-codemirror-DtdPDzrv.js +15 -0
- phoenix/server/static/assets/{vendor-recharts-5jlNaZuF.js → vendor-recharts-A0DA1O99.js} +1 -1
- phoenix/server/thread_server.py +2 -2
- phoenix/server/types.py +18 -0
- phoenix/session/client.py +5 -3
- phoenix/session/session.py +2 -2
- phoenix/trace/dsl/filter.py +2 -6
- phoenix/trace/fixtures.py +17 -23
- phoenix/trace/utils.py +23 -0
- phoenix/utilities/client.py +116 -0
- phoenix/utilities/project.py +1 -1
- phoenix/version.py +1 -1
- phoenix/server/api/routers/v1/dataset_examples.py +0 -178
- phoenix/server/openapi/docs.py +0 -221
- phoenix/server/static/assets/components-DeS0YEmv.js +0 -1142
- phoenix/server/static/assets/vendor-codemirror-Cqwpwlua.js +0 -12
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.14.1.dist-info → arize_phoenix-4.16.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
+
from typing import Any, List, Optional
|
|
2
3
|
|
|
4
|
+
from fastapi import APIRouter, HTTPException
|
|
5
|
+
from pydantic import Field
|
|
3
6
|
from sqlalchemy import select
|
|
4
7
|
from starlette.requests import Request
|
|
5
|
-
from starlette.responses import JSONResponse, Response
|
|
6
8
|
from starlette.status import HTTP_404_NOT_FOUND
|
|
7
9
|
from strawberry.relay import GlobalID
|
|
8
10
|
|
|
@@ -10,188 +12,129 @@ from phoenix.db import models
|
|
|
10
12
|
from phoenix.db.models import ExperimentRunOutput
|
|
11
13
|
from phoenix.server.api.types.node import from_global_id_with_expected_type
|
|
12
14
|
|
|
15
|
+
from .pydantic_compat import V1RoutesBaseModel
|
|
16
|
+
from .utils import ResponseBody, add_errors_to_responses
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
responses:
|
|
65
|
-
200:
|
|
66
|
-
description: Experiment run created successfully
|
|
67
|
-
content:
|
|
68
|
-
application/json:
|
|
69
|
-
schema:
|
|
70
|
-
type: object
|
|
71
|
-
properties:
|
|
72
|
-
data:
|
|
73
|
-
type: object
|
|
74
|
-
properties:
|
|
75
|
-
id:
|
|
76
|
-
type: string
|
|
77
|
-
description: The ID of the created experiment run
|
|
78
|
-
404:
|
|
79
|
-
description: Experiment or DatasetExample not found
|
|
80
|
-
"""
|
|
81
|
-
experiment_gid = GlobalID.from_id(request.path_params["experiment_id"])
|
|
18
|
+
router = APIRouter(tags=["experiments"], include_in_schema=False)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ExperimentRun(V1RoutesBaseModel):
|
|
22
|
+
dataset_example_id: str = Field(
|
|
23
|
+
description="The ID of the dataset example used in the experiment run"
|
|
24
|
+
)
|
|
25
|
+
output: Any = Field(description="The output of the experiment task")
|
|
26
|
+
repetition_number: int = Field(description="The repetition number of the experiment run")
|
|
27
|
+
start_time: datetime = Field(description="The start time of the experiment run")
|
|
28
|
+
end_time: datetime = Field(description="The end time of the experiment run")
|
|
29
|
+
trace_id: Optional[str] = Field(
|
|
30
|
+
default=None, description="The ID of the corresponding trace (if one exists)"
|
|
31
|
+
)
|
|
32
|
+
error: Optional[str] = Field(
|
|
33
|
+
default=None,
|
|
34
|
+
description="Optional error message if the experiment run encountered an error",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class CreateExperimentRunRequestBody(ExperimentRun):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CreateExperimentRunResponseBodyData(V1RoutesBaseModel):
|
|
43
|
+
id: str = Field(description="The ID of the newly created experiment run")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CreateExperimentResponseBody(ResponseBody[CreateExperimentRunResponseBodyData]):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@router.post(
|
|
51
|
+
"/experiments/{experiment_id}/runs",
|
|
52
|
+
operation_id="createExperimentRun",
|
|
53
|
+
summary="Create run for an experiment",
|
|
54
|
+
response_description="Experiment run created successfully",
|
|
55
|
+
responses=add_errors_to_responses(
|
|
56
|
+
[
|
|
57
|
+
{
|
|
58
|
+
"status_code": HTTP_404_NOT_FOUND,
|
|
59
|
+
"description": "Experiment or dataset example not found",
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
async def create_experiment_run(
|
|
65
|
+
request: Request, experiment_id: str, request_body: CreateExperimentRunRequestBody
|
|
66
|
+
) -> CreateExperimentResponseBody:
|
|
67
|
+
experiment_gid = GlobalID.from_id(experiment_id)
|
|
82
68
|
try:
|
|
83
|
-
|
|
69
|
+
experiment_rowid = from_global_id_with_expected_type(experiment_gid, "Experiment")
|
|
84
70
|
except ValueError:
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
raise HTTPException(
|
|
72
|
+
detail=f"Experiment with ID {experiment_gid} does not exist",
|
|
87
73
|
status_code=HTTP_404_NOT_FOUND,
|
|
88
74
|
)
|
|
89
75
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
example_gid = GlobalID.from_id(payload["dataset_example_id"])
|
|
76
|
+
example_gid = GlobalID.from_id(request_body.dataset_example_id)
|
|
93
77
|
try:
|
|
94
78
|
dataset_example_id = from_global_id_with_expected_type(example_gid, "DatasetExample")
|
|
95
79
|
except ValueError:
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
raise HTTPException(
|
|
81
|
+
detail=f"DatasetExample with ID {example_gid} does not exist",
|
|
98
82
|
status_code=HTTP_404_NOT_FOUND,
|
|
99
83
|
)
|
|
100
84
|
|
|
101
|
-
trace_id =
|
|
102
|
-
task_output =
|
|
103
|
-
repetition_number =
|
|
104
|
-
start_time =
|
|
105
|
-
end_time =
|
|
106
|
-
error =
|
|
85
|
+
trace_id = request_body.trace_id
|
|
86
|
+
task_output = request_body.output
|
|
87
|
+
repetition_number = request_body.repetition_number
|
|
88
|
+
start_time = request_body.start_time
|
|
89
|
+
end_time = request_body.end_time
|
|
90
|
+
error = request_body.error
|
|
107
91
|
|
|
108
92
|
async with request.app.state.db() as session:
|
|
109
93
|
exp_run = models.ExperimentRun(
|
|
110
|
-
experiment_id=
|
|
94
|
+
experiment_id=experiment_rowid,
|
|
111
95
|
dataset_example_id=dataset_example_id,
|
|
112
96
|
trace_id=trace_id,
|
|
113
97
|
output=ExperimentRunOutput(task_output=task_output),
|
|
114
98
|
repetition_number=repetition_number,
|
|
115
|
-
start_time=
|
|
116
|
-
end_time=
|
|
99
|
+
start_time=start_time,
|
|
100
|
+
end_time=end_time,
|
|
117
101
|
error=error,
|
|
118
102
|
)
|
|
119
103
|
session.add(exp_run)
|
|
120
104
|
await session.flush()
|
|
121
105
|
run_gid = GlobalID("ExperimentRun", str(exp_run.id))
|
|
122
|
-
return
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
application/json:
|
|
143
|
-
schema:
|
|
144
|
-
type: object
|
|
145
|
-
properties:
|
|
146
|
-
data:
|
|
147
|
-
type: array
|
|
148
|
-
items:
|
|
149
|
-
type: object
|
|
150
|
-
properties:
|
|
151
|
-
id:
|
|
152
|
-
type: string
|
|
153
|
-
description: The ID of the experiment run
|
|
154
|
-
experiment_id:
|
|
155
|
-
type: string
|
|
156
|
-
description: The ID of the experiment
|
|
157
|
-
dataset_example_id:
|
|
158
|
-
type: string
|
|
159
|
-
description: The ID of the dataset example
|
|
160
|
-
repetition_number:
|
|
161
|
-
type: integer
|
|
162
|
-
description: The repetition number of the experiment run
|
|
163
|
-
start_time:
|
|
164
|
-
type: string
|
|
165
|
-
format: date-time
|
|
166
|
-
description: The start time of the experiment run in ISO format
|
|
167
|
-
end_time:
|
|
168
|
-
type: string
|
|
169
|
-
format: date-time
|
|
170
|
-
description: The end time of the experiment run in ISO format
|
|
171
|
-
output:
|
|
172
|
-
description: The output of the experiment task
|
|
173
|
-
error:
|
|
174
|
-
type: string
|
|
175
|
-
description: Error message if the experiment run encountered an error
|
|
176
|
-
trace_id:
|
|
177
|
-
type: string
|
|
178
|
-
description: Optional trace ID for tracking
|
|
179
|
-
404:
|
|
180
|
-
description: Experiment not found
|
|
181
|
-
"""
|
|
182
|
-
experiment_gid = GlobalID.from_id(request.path_params["experiment_id"])
|
|
106
|
+
return CreateExperimentResponseBody(data=CreateExperimentRunResponseBodyData(id=str(run_gid)))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class ListExperimentRunsResponseBody(ResponseBody[List[ExperimentRun]]):
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@router.get(
|
|
114
|
+
"/experiments/{experiment_id}/runs",
|
|
115
|
+
operation_id="listExperimentRuns",
|
|
116
|
+
summary="List runs for an experiment",
|
|
117
|
+
response_description="Experiment runs retrieved successfully",
|
|
118
|
+
responses=add_errors_to_responses(
|
|
119
|
+
[{"status_code": HTTP_404_NOT_FOUND, "description": "Experiment not found"}]
|
|
120
|
+
),
|
|
121
|
+
)
|
|
122
|
+
async def list_experiment_runs(
|
|
123
|
+
request: Request, experiment_id: str
|
|
124
|
+
) -> ListExperimentRunsResponseBody:
|
|
125
|
+
experiment_gid = GlobalID.from_id(experiment_id)
|
|
183
126
|
try:
|
|
184
|
-
|
|
127
|
+
experiment_rowid = from_global_id_with_expected_type(experiment_gid, "Experiment")
|
|
185
128
|
except ValueError:
|
|
186
|
-
|
|
187
|
-
|
|
129
|
+
raise HTTPException(
|
|
130
|
+
detail=f"Experiment with ID {experiment_gid} does not exist",
|
|
188
131
|
status_code=HTTP_404_NOT_FOUND,
|
|
189
132
|
)
|
|
190
133
|
|
|
191
134
|
async with request.app.state.db() as session:
|
|
192
135
|
experiment_runs = await session.execute(
|
|
193
136
|
select(models.ExperimentRun)
|
|
194
|
-
.where(models.ExperimentRun.experiment_id ==
|
|
137
|
+
.where(models.ExperimentRun.experiment_id == experiment_rowid)
|
|
195
138
|
# order by dataset_example_id to be consistent with `list_dataset_examples`
|
|
196
139
|
.order_by(models.ExperimentRun.dataset_example_id.asc())
|
|
197
140
|
)
|
|
@@ -202,9 +145,9 @@ async def list_experiment_runs(request: Request) -> Response:
|
|
|
202
145
|
experiment_gid = GlobalID("Experiment", str(exp_run.experiment_id))
|
|
203
146
|
example_gid = GlobalID("DatasetExample", str(exp_run.dataset_example_id))
|
|
204
147
|
runs.append(
|
|
205
|
-
|
|
206
|
-
start_time=exp_run.start_time
|
|
207
|
-
end_time=exp_run.end_time
|
|
148
|
+
ExperimentRun(
|
|
149
|
+
start_time=exp_run.start_time,
|
|
150
|
+
end_time=exp_run.end_time,
|
|
208
151
|
experiment_id=str(experiment_gid),
|
|
209
152
|
dataset_example_id=str(example_gid),
|
|
210
153
|
repetition_number=exp_run.repetition_number,
|
|
@@ -214,4 +157,4 @@ async def list_experiment_runs(request: Request) -> Response:
|
|
|
214
157
|
trace_id=exp_run.trace_id,
|
|
215
158
|
)
|
|
216
159
|
)
|
|
217
|
-
return
|
|
160
|
+
return ListExperimentRunsResponseBody(data=runs)
|