arize-phoenix 8.8.0__py3-none-any.whl → 8.10.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-8.8.0.dist-info → arize_phoenix-8.10.0.dist-info}/METADATA +4 -4
- {arize_phoenix-8.8.0.dist-info → arize_phoenix-8.10.0.dist-info}/RECORD +30 -29
- phoenix/config.py +11 -0
- phoenix/experiments/types.py +2 -0
- phoenix/server/api/helpers/playground_clients.py +30 -2
- phoenix/server/api/helpers/prompts/models.py +23 -2
- phoenix/server/api/input_types/InvocationParameters.py +1 -0
- phoenix/server/api/mutations/__init__.py +3 -1
- phoenix/server/api/mutations/prompt_label_mutations.py +6 -5
- phoenix/server/api/mutations/prompt_mutations.py +6 -5
- phoenix/server/api/mutations/prompt_version_tag_mutations.py +3 -2
- phoenix/server/api/mutations/trace_mutations.py +74 -0
- phoenix/server/api/queries.py +14 -1
- phoenix/server/api/routers/v1/experiments.py +103 -2
- phoenix/server/api/routers/v1/prompts.py +14 -2
- phoenix/server/app.py +1 -1
- phoenix/server/static/.vite/manifest.json +44 -44
- phoenix/server/static/assets/{components-Cvwn-4Sk.js → components-CVzKofML.js} +245 -238
- phoenix/server/static/assets/{index-Cxmc6_pQ.js → index-Ctff7oin.js} +1 -1
- phoenix/server/static/assets/{pages-DLMdDkgQ.js → pages-CVFLHgre.js} +349 -340
- phoenix/server/static/assets/{vendor-yn6w6Ozi.js → vendor-VJCVsFqd.js} +161 -161
- phoenix/server/static/assets/{vendor-arizeai-DoGO67dU.js → vendor-arizeai-BiZagY4a.js} +22 -22
- phoenix/server/static/assets/{vendor-codemirror-BLdSYxpm.js → vendor-codemirror-0mUqu36F.js} +11 -11
- phoenix/server/static/assets/{vendor-recharts-CjOpOw1c.js → vendor-recharts-CfKQSOmq.js} +1 -1
- phoenix/server/static/assets/{vendor-shiki-BwTCxCQY.js → vendor-shiki-BsgMOuir.js} +1 -1
- phoenix/version.py +1 -1
- {arize_phoenix-8.8.0.dist-info → arize_phoenix-8.10.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-8.8.0.dist-info → arize_phoenix-8.10.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-8.8.0.dist-info → arize_phoenix-8.10.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-8.8.0.dist-info → arize_phoenix-8.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
import json
|
|
1
2
|
from datetime import datetime
|
|
2
3
|
from random import getrandbits
|
|
3
4
|
from typing import Any, Optional
|
|
4
5
|
|
|
5
|
-
from fastapi import APIRouter, HTTPException, Path
|
|
6
|
+
from fastapi import APIRouter, HTTPException, Path, Response
|
|
6
7
|
from pydantic import Field
|
|
7
|
-
from sqlalchemy import select
|
|
8
|
+
from sqlalchemy import and_, func, select
|
|
8
9
|
from starlette.requests import Request
|
|
10
|
+
from starlette.responses import PlainTextResponse
|
|
9
11
|
from starlette.status import HTTP_404_NOT_FOUND
|
|
10
12
|
from strawberry.relay import GlobalID
|
|
11
13
|
|
|
@@ -306,3 +308,102 @@ async def list_experiments(
|
|
|
306
308
|
]
|
|
307
309
|
|
|
308
310
|
return ListExperimentsResponseBody(data=data)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@router.get(
|
|
314
|
+
"/experiments/{experiment_id}/json",
|
|
315
|
+
operation_id="getExperimentJSON",
|
|
316
|
+
summary="Download experiment runs as a JSON file",
|
|
317
|
+
response_class=PlainTextResponse,
|
|
318
|
+
responses=add_errors_to_responses(
|
|
319
|
+
[
|
|
320
|
+
{"status_code": HTTP_404_NOT_FOUND, "description": "Experiment not found"},
|
|
321
|
+
]
|
|
322
|
+
),
|
|
323
|
+
)
|
|
324
|
+
async def get_experiment_jsonl(
|
|
325
|
+
request: Request,
|
|
326
|
+
response: Response,
|
|
327
|
+
experiment_id: str = Path(..., title="Experiment ID"),
|
|
328
|
+
) -> str:
|
|
329
|
+
experiment_globalid = GlobalID.from_id(experiment_id)
|
|
330
|
+
try:
|
|
331
|
+
experiment_rowid = from_global_id_with_expected_type(experiment_globalid, "Experiment")
|
|
332
|
+
except ValueError:
|
|
333
|
+
raise HTTPException(
|
|
334
|
+
detail=f"Experiment with ID {experiment_globalid} does not exist",
|
|
335
|
+
status_code=HTTP_404_NOT_FOUND,
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
async with request.app.state.db() as session:
|
|
339
|
+
experiment = await session.get(models.Experiment, experiment_rowid)
|
|
340
|
+
if not experiment:
|
|
341
|
+
raise HTTPException(
|
|
342
|
+
detail=f"Experiment with ID {experiment_globalid} does not exist",
|
|
343
|
+
status_code=HTTP_404_NOT_FOUND,
|
|
344
|
+
)
|
|
345
|
+
revision_ids = (
|
|
346
|
+
select(func.max(models.DatasetExampleRevision.id))
|
|
347
|
+
.join(
|
|
348
|
+
models.DatasetExample,
|
|
349
|
+
models.DatasetExample.id == models.DatasetExampleRevision.dataset_example_id,
|
|
350
|
+
)
|
|
351
|
+
.where(
|
|
352
|
+
and_(
|
|
353
|
+
models.DatasetExampleRevision.dataset_version_id
|
|
354
|
+
<= experiment.dataset_version_id,
|
|
355
|
+
models.DatasetExample.dataset_id == experiment.dataset_id,
|
|
356
|
+
)
|
|
357
|
+
)
|
|
358
|
+
.group_by(models.DatasetExampleRevision.dataset_example_id)
|
|
359
|
+
.scalar_subquery()
|
|
360
|
+
)
|
|
361
|
+
runs_and_revisions = (
|
|
362
|
+
await session.execute(
|
|
363
|
+
select(models.ExperimentRun, models.DatasetExampleRevision)
|
|
364
|
+
.join(
|
|
365
|
+
models.DatasetExample,
|
|
366
|
+
models.DatasetExample.id == models.ExperimentRun.dataset_example_id,
|
|
367
|
+
)
|
|
368
|
+
.join(
|
|
369
|
+
models.DatasetExampleRevision,
|
|
370
|
+
and_(
|
|
371
|
+
models.DatasetExample.id
|
|
372
|
+
== models.DatasetExampleRevision.dataset_example_id,
|
|
373
|
+
models.DatasetExampleRevision.id.in_(revision_ids),
|
|
374
|
+
models.DatasetExampleRevision.revision_kind != "DELETE",
|
|
375
|
+
),
|
|
376
|
+
)
|
|
377
|
+
.where(models.ExperimentRun.experiment_id == experiment_rowid)
|
|
378
|
+
.order_by(
|
|
379
|
+
models.ExperimentRun.dataset_example_id, models.ExperimentRun.repetition_number
|
|
380
|
+
)
|
|
381
|
+
)
|
|
382
|
+
).all()
|
|
383
|
+
if not runs_and_revisions:
|
|
384
|
+
raise HTTPException(
|
|
385
|
+
detail=f"Experiment with ID {experiment_globalid} has no runs",
|
|
386
|
+
status_code=HTTP_404_NOT_FOUND,
|
|
387
|
+
)
|
|
388
|
+
records = []
|
|
389
|
+
for run, revision in runs_and_revisions:
|
|
390
|
+
record = {
|
|
391
|
+
"example_id": str(
|
|
392
|
+
GlobalID(models.DatasetExample.__name__, str(run.dataset_example_id))
|
|
393
|
+
),
|
|
394
|
+
"repetition_number": run.repetition_number,
|
|
395
|
+
"input": revision.input,
|
|
396
|
+
"reference_output": revision.output,
|
|
397
|
+
"output": run.output,
|
|
398
|
+
"error": run.error,
|
|
399
|
+
"latency_ms": run.latency_ms,
|
|
400
|
+
"start_time": run.start_time.isoformat(),
|
|
401
|
+
"end_time": run.end_time.isoformat(),
|
|
402
|
+
"trace_id": run.trace_id,
|
|
403
|
+
"prompt_token_count": run.prompt_token_count,
|
|
404
|
+
"completion_token_count": run.completion_token_count,
|
|
405
|
+
}
|
|
406
|
+
records.append(record)
|
|
407
|
+
|
|
408
|
+
response.headers["content-disposition"] = f'attachment; filename="{experiment.name}.json"'
|
|
409
|
+
return json.dumps(records, ensure_ascii=False, indent=2)
|
|
@@ -2,13 +2,13 @@ import logging
|
|
|
2
2
|
from typing import Any, Optional, Union
|
|
3
3
|
|
|
4
4
|
from fastapi import APIRouter, HTTPException, Path, Query
|
|
5
|
-
from pydantic import ValidationError
|
|
5
|
+
from pydantic import ValidationError, model_validator
|
|
6
6
|
from sqlalchemy import select
|
|
7
7
|
from sqlalchemy.sql import Select
|
|
8
8
|
from starlette.requests import Request
|
|
9
9
|
from starlette.status import HTTP_404_NOT_FOUND, HTTP_422_UNPROCESSABLE_ENTITY
|
|
10
10
|
from strawberry.relay import GlobalID
|
|
11
|
-
from typing_extensions import TypeAlias, assert_never
|
|
11
|
+
from typing_extensions import Self, TypeAlias, assert_never
|
|
12
12
|
|
|
13
13
|
from phoenix.db import models
|
|
14
14
|
from phoenix.db.types.identifier import Identifier
|
|
@@ -52,6 +52,18 @@ class PromptVersionData(V1RoutesBaseModel):
|
|
|
52
52
|
tools: Optional[PromptTools] = None
|
|
53
53
|
response_format: Optional[PromptResponseFormat] = None
|
|
54
54
|
|
|
55
|
+
@model_validator(mode="after")
|
|
56
|
+
def check_template_type_match(self) -> Self:
|
|
57
|
+
if self.template_type is PromptTemplateType.CHAT:
|
|
58
|
+
if self.template.type == "chat":
|
|
59
|
+
return self
|
|
60
|
+
elif self.template_type is PromptTemplateType.STRING:
|
|
61
|
+
if self.template.type == "string":
|
|
62
|
+
return self
|
|
63
|
+
else:
|
|
64
|
+
assert_never(self.template_type)
|
|
65
|
+
raise ValueError("Template type does not match template")
|
|
66
|
+
|
|
55
67
|
|
|
56
68
|
class PromptVersion(PromptVersionData):
|
|
57
69
|
id: str
|
phoenix/server/app.py
CHANGED
|
@@ -549,7 +549,7 @@ def create_graphql_router(
|
|
|
549
549
|
read_only: bool = False,
|
|
550
550
|
secret: Optional[str] = None,
|
|
551
551
|
token_store: Optional[TokenStore] = None,
|
|
552
|
-
) -> GraphQLRouter
|
|
552
|
+
) -> GraphQLRouter[Context, None]:
|
|
553
553
|
"""Creates the GraphQL router.
|
|
554
554
|
|
|
555
555
|
Args:
|
|
@@ -1,87 +1,87 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_components-
|
|
3
|
-
"file": "assets/components-
|
|
2
|
+
"_components-CVzKofML.js": {
|
|
3
|
+
"file": "assets/components-CVzKofML.js",
|
|
4
4
|
"name": "components",
|
|
5
5
|
"imports": [
|
|
6
|
-
"_vendor-
|
|
7
|
-
"_pages-
|
|
8
|
-
"_vendor-arizeai-
|
|
9
|
-
"_vendor-codemirror-
|
|
6
|
+
"_vendor-VJCVsFqd.js",
|
|
7
|
+
"_pages-CVFLHgre.js",
|
|
8
|
+
"_vendor-arizeai-BiZagY4a.js",
|
|
9
|
+
"_vendor-codemirror-0mUqu36F.js",
|
|
10
10
|
"_vendor-three-C-AGeJYv.js"
|
|
11
11
|
]
|
|
12
12
|
},
|
|
13
|
-
"_pages-
|
|
14
|
-
"file": "assets/pages-
|
|
13
|
+
"_pages-CVFLHgre.js": {
|
|
14
|
+
"file": "assets/pages-CVFLHgre.js",
|
|
15
15
|
"name": "pages",
|
|
16
16
|
"imports": [
|
|
17
|
-
"_vendor-
|
|
18
|
-
"_vendor-arizeai-
|
|
19
|
-
"_components-
|
|
20
|
-
"_vendor-codemirror-
|
|
21
|
-
"_vendor-recharts-
|
|
17
|
+
"_vendor-VJCVsFqd.js",
|
|
18
|
+
"_vendor-arizeai-BiZagY4a.js",
|
|
19
|
+
"_components-CVzKofML.js",
|
|
20
|
+
"_vendor-codemirror-0mUqu36F.js",
|
|
21
|
+
"_vendor-recharts-CfKQSOmq.js"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
24
|
"_vendor-Cg6lcjUC.css": {
|
|
25
25
|
"file": "assets/vendor-Cg6lcjUC.css",
|
|
26
26
|
"src": "_vendor-Cg6lcjUC.css"
|
|
27
27
|
},
|
|
28
|
-
"_vendor-
|
|
29
|
-
"file": "assets/vendor-
|
|
28
|
+
"_vendor-VJCVsFqd.js": {
|
|
29
|
+
"file": "assets/vendor-VJCVsFqd.js",
|
|
30
|
+
"name": "vendor",
|
|
31
|
+
"imports": [
|
|
32
|
+
"_vendor-three-C-AGeJYv.js"
|
|
33
|
+
],
|
|
34
|
+
"css": [
|
|
35
|
+
"assets/vendor-Cg6lcjUC.css"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"_vendor-arizeai-BiZagY4a.js": {
|
|
39
|
+
"file": "assets/vendor-arizeai-BiZagY4a.js",
|
|
30
40
|
"name": "vendor-arizeai",
|
|
31
41
|
"imports": [
|
|
32
|
-
"_vendor-
|
|
42
|
+
"_vendor-VJCVsFqd.js"
|
|
33
43
|
]
|
|
34
44
|
},
|
|
35
|
-
"_vendor-codemirror-
|
|
36
|
-
"file": "assets/vendor-codemirror-
|
|
45
|
+
"_vendor-codemirror-0mUqu36F.js": {
|
|
46
|
+
"file": "assets/vendor-codemirror-0mUqu36F.js",
|
|
37
47
|
"name": "vendor-codemirror",
|
|
38
48
|
"imports": [
|
|
39
|
-
"_vendor-
|
|
40
|
-
"_vendor-shiki-
|
|
49
|
+
"_vendor-VJCVsFqd.js",
|
|
50
|
+
"_vendor-shiki-BsgMOuir.js"
|
|
41
51
|
]
|
|
42
52
|
},
|
|
43
|
-
"_vendor-recharts-
|
|
44
|
-
"file": "assets/vendor-recharts-
|
|
53
|
+
"_vendor-recharts-CfKQSOmq.js": {
|
|
54
|
+
"file": "assets/vendor-recharts-CfKQSOmq.js",
|
|
45
55
|
"name": "vendor-recharts",
|
|
46
56
|
"imports": [
|
|
47
|
-
"_vendor-
|
|
57
|
+
"_vendor-VJCVsFqd.js"
|
|
48
58
|
]
|
|
49
59
|
},
|
|
50
|
-
"_vendor-shiki-
|
|
51
|
-
"file": "assets/vendor-shiki-
|
|
60
|
+
"_vendor-shiki-BsgMOuir.js": {
|
|
61
|
+
"file": "assets/vendor-shiki-BsgMOuir.js",
|
|
52
62
|
"name": "vendor-shiki",
|
|
53
63
|
"imports": [
|
|
54
|
-
"_vendor-
|
|
64
|
+
"_vendor-VJCVsFqd.js"
|
|
55
65
|
]
|
|
56
66
|
},
|
|
57
67
|
"_vendor-three-C-AGeJYv.js": {
|
|
58
68
|
"file": "assets/vendor-three-C-AGeJYv.js",
|
|
59
69
|
"name": "vendor-three"
|
|
60
70
|
},
|
|
61
|
-
"_vendor-yn6w6Ozi.js": {
|
|
62
|
-
"file": "assets/vendor-yn6w6Ozi.js",
|
|
63
|
-
"name": "vendor",
|
|
64
|
-
"imports": [
|
|
65
|
-
"_vendor-three-C-AGeJYv.js"
|
|
66
|
-
],
|
|
67
|
-
"css": [
|
|
68
|
-
"assets/vendor-Cg6lcjUC.css"
|
|
69
|
-
]
|
|
70
|
-
},
|
|
71
71
|
"index.tsx": {
|
|
72
|
-
"file": "assets/index-
|
|
72
|
+
"file": "assets/index-Ctff7oin.js",
|
|
73
73
|
"name": "index",
|
|
74
74
|
"src": "index.tsx",
|
|
75
75
|
"isEntry": true,
|
|
76
76
|
"imports": [
|
|
77
|
-
"_vendor-
|
|
78
|
-
"_vendor-arizeai-
|
|
79
|
-
"_pages-
|
|
80
|
-
"_components-
|
|
77
|
+
"_vendor-VJCVsFqd.js",
|
|
78
|
+
"_vendor-arizeai-BiZagY4a.js",
|
|
79
|
+
"_pages-CVFLHgre.js",
|
|
80
|
+
"_components-CVzKofML.js",
|
|
81
81
|
"_vendor-three-C-AGeJYv.js",
|
|
82
|
-
"_vendor-codemirror-
|
|
83
|
-
"_vendor-shiki-
|
|
84
|
-
"_vendor-recharts-
|
|
82
|
+
"_vendor-codemirror-0mUqu36F.js",
|
|
83
|
+
"_vendor-shiki-BsgMOuir.js",
|
|
84
|
+
"_vendor-recharts-CfKQSOmq.js"
|
|
85
85
|
]
|
|
86
86
|
}
|
|
87
87
|
}
|