arize-phoenix 4.10.2rc0__py3-none-any.whl → 4.10.2rc1__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.

Files changed (38) hide show
  1. {arize_phoenix-4.10.2rc0.dist-info → arize_phoenix-4.10.2rc1.dist-info}/METADATA +4 -3
  2. {arize_phoenix-4.10.2rc0.dist-info → arize_phoenix-4.10.2rc1.dist-info}/RECORD +27 -35
  3. phoenix/server/api/context.py +3 -7
  4. phoenix/server/api/openapi/main.py +18 -2
  5. phoenix/server/api/openapi/schema.py +12 -12
  6. phoenix/server/api/routers/v1/__init__.py +36 -83
  7. phoenix/server/api/routers/v1/dataset_examples.py +102 -123
  8. phoenix/server/api/routers/v1/datasets.py +389 -507
  9. phoenix/server/api/routers/v1/evaluations.py +74 -64
  10. phoenix/server/api/routers/v1/experiment_evaluations.py +67 -91
  11. phoenix/server/api/routers/v1/experiment_runs.py +97 -155
  12. phoenix/server/api/routers/v1/experiments.py +131 -181
  13. phoenix/server/api/routers/v1/spans.py +141 -173
  14. phoenix/server/api/routers/v1/traces.py +113 -128
  15. phoenix/server/api/routers/v1/utils.py +94 -0
  16. phoenix/server/api/types/Span.py +0 -1
  17. phoenix/server/app.py +148 -192
  18. phoenix/server/main.py +0 -3
  19. phoenix/server/static/index.css +6 -0
  20. phoenix/server/static/index.js +8547 -0
  21. phoenix/server/templates/index.html +25 -76
  22. phoenix/server/thread_server.py +2 -2
  23. phoenix/trace/schemas.py +0 -1
  24. phoenix/version.py +1 -1
  25. phoenix/server/openapi/docs.py +0 -221
  26. phoenix/server/static/.vite/manifest.json +0 -78
  27. phoenix/server/static/assets/components-C8sm_r1F.js +0 -1142
  28. phoenix/server/static/assets/index-BEKPzgQs.js +0 -100
  29. phoenix/server/static/assets/pages-bN7juCjh.js +0 -2885
  30. phoenix/server/static/assets/vendor-CUDAPm8e.js +0 -641
  31. phoenix/server/static/assets/vendor-DxkFTwjz.css +0 -1
  32. phoenix/server/static/assets/vendor-arizeai-Do2HOmcL.js +0 -662
  33. phoenix/server/static/assets/vendor-codemirror-CrdxOlMs.js +0 -12
  34. phoenix/server/static/assets/vendor-recharts-PKRvByVe.js +0 -59
  35. phoenix/server/static/assets/vendor-three-DwGkEfCM.js +0 -2998
  36. {arize_phoenix-4.10.2rc0.dist-info → arize_phoenix-4.10.2rc1.dist-info}/WHEEL +0 -0
  37. {arize_phoenix-4.10.2rc0.dist-info → arize_phoenix-4.10.2rc1.dist-info}/licenses/IP_NOTICE +0 -0
  38. {arize_phoenix-4.10.2rc0.dist-info → arize_phoenix-4.10.2rc1.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 BaseModel, 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,128 @@ 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 .utils import ResponseBody, add_errors_to_responses
13
16
 
14
- async def create_experiment_run(request: Request) -> Response:
15
- """
16
- summary: Create a new experiment run for a specific experiment
17
- operationId: createExperimentRun
18
- tags:
19
- - private
20
- parameters:
21
- - in: path
22
- name: experiment_id
23
- required: true
24
- description: The ID of the experiment for which the run is being created
25
- schema:
26
- type: string
27
- requestBody:
28
- description: Details of the experiment run to be created
29
- required: true
30
- content:
31
- application/json:
32
- schema:
33
- type: object
34
- properties:
35
- dataset_example_id:
36
- type: string
37
- description: The ID of the dataset example used in the experiment run
38
- trace_id:
39
- type: string
40
- description: Optional trace ID for tracking
41
- output:
42
- description: The output of the experiment task
43
- repetition_number:
44
- type: integer
45
- description: The repetition number of the experiment run
46
- start_time:
47
- type: string
48
- format: date-time
49
- description: The start time of the experiment run in ISO format
50
- end_time:
51
- type: string
52
- format: date-time
53
- description: The end time of the experiment run in ISO format
54
- error:
55
- type: string
56
- description: Optional error message if the experiment run encountered an error
57
- nullable: true
58
- required:
59
- - dataset_example_id
60
- - output
61
- - repetition_number
62
- - start_time
63
- - end_time
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"])
17
+ router = APIRouter(tags=["experiments"], include_in_schema=False)
18
+
19
+
20
+ class ExperimentRun(BaseModel):
21
+ dataset_example_id: str = Field(
22
+ description="The ID of the dataset example used in the experiment run"
23
+ )
24
+ output: Any = Field(description="The output of the experiment task")
25
+ repetition_number: int = Field(description="The repetition number of the experiment run")
26
+ start_time: datetime = Field(description="The start time of the experiment run")
27
+ end_time: datetime = Field(description="The end time of the experiment run")
28
+ trace_id: Optional[str] = Field(
29
+ default=None, description="The ID of the corresponding trace (if one exists)"
30
+ )
31
+ error: Optional[str] = Field(
32
+ default=None,
33
+ description="Optional error message if the experiment run encountered an error",
34
+ )
35
+
36
+
37
+ class CreateExperimentRunRequestBody(ExperimentRun):
38
+ pass
39
+
40
+
41
+ class CreateExperimentRunResponseBodyData(BaseModel):
42
+ id: str = Field(description="The ID of the newly created experiment run")
43
+
44
+
45
+ class CreateExperimentResponseBody(ResponseBody[CreateExperimentRunResponseBodyData]):
46
+ pass
47
+
48
+
49
+ @router.post(
50
+ "/experiments/{experiment_id}/runs",
51
+ operation_id="createExperimentRun",
52
+ summary="Create run for an experiment",
53
+ response_description="Experiment run created successfully",
54
+ responses=add_errors_to_responses(
55
+ [
56
+ {
57
+ "status_code": HTTP_404_NOT_FOUND,
58
+ "description": "Experiment or dataset example not found",
59
+ }
60
+ ]
61
+ ),
62
+ )
63
+ async def create_experiment_run(
64
+ request: Request, experiment_id: str, request_body: CreateExperimentRunRequestBody
65
+ ) -> CreateExperimentResponseBody:
66
+ experiment_gid = GlobalID.from_id(experiment_id)
82
67
  try:
83
- experiment_id = from_global_id_with_expected_type(experiment_gid, "Experiment")
68
+ experiment_rowid = from_global_id_with_expected_type(experiment_gid, "Experiment")
84
69
  except ValueError:
85
- return Response(
86
- content=f"Experiment with ID {experiment_gid} does not exist",
70
+ raise HTTPException(
71
+ detail=f"Experiment with ID {experiment_gid} does not exist",
87
72
  status_code=HTTP_404_NOT_FOUND,
88
73
  )
89
74
 
90
- payload = await request.json()
91
-
92
- example_gid = GlobalID.from_id(payload["dataset_example_id"])
75
+ example_gid = GlobalID.from_id(request_body.dataset_example_id)
93
76
  try:
94
77
  dataset_example_id = from_global_id_with_expected_type(example_gid, "DatasetExample")
95
78
  except ValueError:
96
- return Response(
97
- content=f"DatasetExample with ID {example_gid} does not exist",
79
+ raise HTTPException(
80
+ detail=f"DatasetExample with ID {example_gid} does not exist",
98
81
  status_code=HTTP_404_NOT_FOUND,
99
82
  )
100
83
 
101
- trace_id = payload.get("trace_id", None)
102
- task_output = payload["output"]
103
- repetition_number = payload["repetition_number"]
104
- start_time = payload["start_time"]
105
- end_time = payload["end_time"]
106
- error = payload.get("error")
84
+ trace_id = request_body.trace_id
85
+ task_output = request_body.output
86
+ repetition_number = request_body.repetition_number
87
+ start_time = request_body.start_time
88
+ end_time = request_body.end_time
89
+ error = request_body.error
107
90
 
108
91
  async with request.app.state.db() as session:
109
92
  exp_run = models.ExperimentRun(
110
- experiment_id=experiment_id,
93
+ experiment_id=experiment_rowid,
111
94
  dataset_example_id=dataset_example_id,
112
95
  trace_id=trace_id,
113
96
  output=ExperimentRunOutput(task_output=task_output),
114
97
  repetition_number=repetition_number,
115
- start_time=datetime.fromisoformat(start_time),
116
- end_time=datetime.fromisoformat(end_time),
98
+ start_time=start_time,
99
+ end_time=end_time,
117
100
  error=error,
118
101
  )
119
102
  session.add(exp_run)
120
103
  await session.flush()
121
104
  run_gid = GlobalID("ExperimentRun", str(exp_run.id))
122
- return JSONResponse(content={"data": {"id": str(run_gid)}})
123
-
124
-
125
- async def list_experiment_runs(request: Request) -> Response:
126
- """
127
- summary: List all runs for a specific experiment
128
- operationId: listExperimentRuns
129
- tags:
130
- - private
131
- parameters:
132
- - in: path
133
- name: experiment_id
134
- required: true
135
- description: The ID of the experiment to list runs for
136
- schema:
137
- type: string
138
- responses:
139
- 200:
140
- description: Experiment runs retrieved successfully
141
- content:
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"])
105
+ return CreateExperimentResponseBody(data=CreateExperimentRunResponseBodyData(id=str(run_gid)))
106
+
107
+
108
+ class ListExperimentRunsResponseBody(ResponseBody[List[ExperimentRun]]):
109
+ pass
110
+
111
+
112
+ @router.get(
113
+ "/experiments/{experiment_id}/runs",
114
+ operation_id="listExperimentRuns",
115
+ summary="List runs for an experiment",
116
+ response_description="Experiment runs retrieved successfully",
117
+ responses=add_errors_to_responses(
118
+ [{"status_code": HTTP_404_NOT_FOUND, "description": "Experiment not found"}]
119
+ ),
120
+ )
121
+ async def list_experiment_runs(
122
+ request: Request, experiment_id: str
123
+ ) -> ListExperimentRunsResponseBody:
124
+ experiment_gid = GlobalID.from_id(experiment_id)
183
125
  try:
184
- experiment_id = from_global_id_with_expected_type(experiment_gid, "Experiment")
126
+ experiment_rowid = from_global_id_with_expected_type(experiment_gid, "Experiment")
185
127
  except ValueError:
186
- return Response(
187
- content=f"Experiment with ID {experiment_gid} does not exist",
128
+ raise HTTPException(
129
+ detail=f"Experiment with ID {experiment_gid} does not exist",
188
130
  status_code=HTTP_404_NOT_FOUND,
189
131
  )
190
132
 
191
133
  async with request.app.state.db() as session:
192
134
  experiment_runs = await session.execute(
193
135
  select(models.ExperimentRun)
194
- .where(models.ExperimentRun.experiment_id == experiment_id)
136
+ .where(models.ExperimentRun.experiment_id == experiment_rowid)
195
137
  # order by dataset_example_id to be consistent with `list_dataset_examples`
196
138
  .order_by(models.ExperimentRun.dataset_example_id.asc())
197
139
  )
@@ -202,9 +144,9 @@ async def list_experiment_runs(request: Request) -> Response:
202
144
  experiment_gid = GlobalID("Experiment", str(exp_run.experiment_id))
203
145
  example_gid = GlobalID("DatasetExample", str(exp_run.dataset_example_id))
204
146
  runs.append(
205
- dict(
206
- start_time=exp_run.start_time.isoformat(),
207
- end_time=exp_run.end_time.isoformat(),
147
+ ExperimentRun(
148
+ start_time=exp_run.start_time,
149
+ end_time=exp_run.end_time,
208
150
  experiment_id=str(experiment_gid),
209
151
  dataset_example_id=str(example_gid),
210
152
  repetition_number=exp_run.repetition_number,
@@ -214,4 +156,4 @@ async def list_experiment_runs(request: Request) -> Response:
214
156
  trace_id=exp_run.trace_id,
215
157
  )
216
158
  )
217
- return JSONResponse(content={"data": runs}, status_code=200)
159
+ return ListExperimentRunsResponseBody(data=runs)