arize-phoenix 4.20.0__py3-none-any.whl → 4.20.2__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.20.0.dist-info → arize_phoenix-4.20.2.dist-info}/METADATA +2 -1
- {arize_phoenix-4.20.0.dist-info → arize_phoenix-4.20.2.dist-info}/RECORD +45 -43
- phoenix/db/bulk_inserter.py +24 -98
- phoenix/db/insertion/document_annotation.py +13 -0
- phoenix/db/insertion/span.py +9 -0
- phoenix/db/insertion/span_annotation.py +13 -0
- phoenix/db/insertion/trace_annotation.py +13 -0
- phoenix/db/insertion/types.py +34 -28
- phoenix/db/migrations/versions/10460e46d750_datasets.py +28 -2
- phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +134 -0
- phoenix/db/migrations/versions/cf03bd6bae1d_init.py +28 -2
- phoenix/db/models.py +9 -1
- phoenix/server/api/context.py +8 -6
- phoenix/server/api/dataloaders/__init__.py +0 -47
- phoenix/server/api/dataloaders/token_counts.py +2 -7
- phoenix/server/api/input_types/SpanSort.py +3 -8
- phoenix/server/api/mutations/dataset_mutations.py +9 -3
- phoenix/server/api/mutations/experiment_mutations.py +2 -0
- phoenix/server/api/mutations/project_mutations.py +5 -5
- phoenix/server/api/mutations/span_annotations_mutations.py +10 -2
- phoenix/server/api/mutations/trace_annotations_mutations.py +10 -2
- phoenix/server/api/queries.py +9 -0
- phoenix/server/api/routers/v1/datasets.py +2 -0
- phoenix/server/api/routers/v1/experiment_evaluations.py +2 -0
- phoenix/server/api/routers/v1/experiment_runs.py +2 -0
- phoenix/server/api/routers/v1/experiments.py +2 -0
- phoenix/server/api/routers/v1/spans.py +12 -8
- phoenix/server/api/routers/v1/traces.py +12 -10
- phoenix/server/api/types/Dataset.py +6 -1
- phoenix/server/api/types/Experiment.py +6 -1
- phoenix/server/api/types/Project.py +4 -1
- phoenix/server/api/types/Span.py +5 -17
- phoenix/server/app.py +25 -8
- phoenix/server/dml_event.py +136 -0
- phoenix/server/dml_event_handler.py +272 -0
- phoenix/server/static/.vite/manifest.json +14 -14
- phoenix/server/static/assets/{components-CAummAJx.js → components-BSw2e1Zr.js} +108 -100
- phoenix/server/static/assets/{index-Cg5hdf3g.js → index-BYUFcdtx.js} +1 -1
- phoenix/server/static/assets/{pages-BU__X1UX.js → pages-p_fuED5k.js} +251 -237
- phoenix/server/static/assets/{vendor-arizeai-CkyzG9Wl.js → vendor-arizeai-CIETbKDq.js} +28 -28
- phoenix/server/types.py +106 -1
- phoenix/version.py +1 -1
- phoenix/db/migrations/types.py +0 -29
- {arize_phoenix-4.20.0.dist-info → arize_phoenix-4.20.2.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.20.0.dist-info → arize_phoenix-4.20.2.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.20.0.dist-info → arize_phoenix-4.20.2.dist-info}/licenses/LICENSE +0 -0
phoenix/server/types.py
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
|
-
from
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from asyncio import Task, create_task, sleep
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from typing import (
|
|
6
|
+
Any,
|
|
7
|
+
AsyncContextManager,
|
|
8
|
+
Callable,
|
|
9
|
+
DefaultDict,
|
|
10
|
+
Generic,
|
|
11
|
+
Iterator,
|
|
12
|
+
List,
|
|
13
|
+
Optional,
|
|
14
|
+
Protocol,
|
|
15
|
+
Type,
|
|
16
|
+
TypeVar,
|
|
17
|
+
)
|
|
2
18
|
|
|
19
|
+
from cachetools import LRUCache
|
|
3
20
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
4
21
|
|
|
22
|
+
from phoenix.db import models
|
|
5
23
|
from phoenix.db.helpers import SupportedSQLDialect
|
|
6
24
|
|
|
7
25
|
|
|
26
|
+
class CanSetLastUpdatedAt(Protocol):
|
|
27
|
+
def set(self, table: Type[models.Base], id_: int) -> None: ...
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CanGetLastUpdatedAt(Protocol):
|
|
31
|
+
def get(self, table: Type[models.Base], id_: Optional[int] = None) -> Optional[datetime]: ...
|
|
32
|
+
|
|
33
|
+
|
|
8
34
|
class DbSessionFactory:
|
|
9
35
|
def __init__(
|
|
10
36
|
self,
|
|
@@ -16,3 +42,82 @@ class DbSessionFactory:
|
|
|
16
42
|
|
|
17
43
|
def __call__(self) -> AsyncContextManager[AsyncSession]:
|
|
18
44
|
return self._db()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_AnyT = TypeVar("_AnyT")
|
|
48
|
+
_ItemT_contra = TypeVar("_ItemT_contra", contravariant=True)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CanPutItem(Protocol[_ItemT_contra]):
|
|
52
|
+
def put(self, item: _ItemT_contra) -> None: ...
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class _Batch(CanPutItem[_AnyT], Protocol[_AnyT]):
|
|
56
|
+
@property
|
|
57
|
+
def empty(self) -> bool: ...
|
|
58
|
+
def clear(self) -> None: ...
|
|
59
|
+
def __iter__(self) -> Iterator[_AnyT]: ...
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class _HasBatch(Generic[_ItemT_contra], ABC):
|
|
63
|
+
_batch_factory: Callable[[], _Batch[_ItemT_contra]]
|
|
64
|
+
|
|
65
|
+
def __init__(self) -> None:
|
|
66
|
+
self._batch = self._batch_factory()
|
|
67
|
+
|
|
68
|
+
def put(self, item: _ItemT_contra) -> None:
|
|
69
|
+
self._batch.put(item)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class BatchedCaller(_HasBatch[_AnyT], Generic[_AnyT], ABC):
|
|
73
|
+
def __init__(self, *, sleep_seconds: float = 0.1, **kwargs: Any) -> None:
|
|
74
|
+
assert sleep_seconds > 0
|
|
75
|
+
super().__init__(**kwargs)
|
|
76
|
+
self._running = False
|
|
77
|
+
self._seconds = sleep_seconds
|
|
78
|
+
self._tasks: List[Task[None]] = []
|
|
79
|
+
|
|
80
|
+
async def start(self) -> None:
|
|
81
|
+
self._running = True
|
|
82
|
+
if not self._tasks:
|
|
83
|
+
self._tasks.append(create_task(self._run()))
|
|
84
|
+
|
|
85
|
+
async def stop(self) -> None:
|
|
86
|
+
self._running = False
|
|
87
|
+
for task in reversed(self._tasks):
|
|
88
|
+
if not task.done():
|
|
89
|
+
task.cancel()
|
|
90
|
+
self._tasks.clear()
|
|
91
|
+
|
|
92
|
+
@abstractmethod
|
|
93
|
+
async def __call__(self) -> None: ...
|
|
94
|
+
|
|
95
|
+
async def _run(self) -> None:
|
|
96
|
+
while self._running:
|
|
97
|
+
self._tasks.append(create_task(sleep(self._seconds)))
|
|
98
|
+
await self._tasks[-1]
|
|
99
|
+
self._tasks.pop()
|
|
100
|
+
if self._batch.empty:
|
|
101
|
+
continue
|
|
102
|
+
self._tasks.append(create_task(self()))
|
|
103
|
+
await self._tasks[-1]
|
|
104
|
+
self._tasks.pop()
|
|
105
|
+
self._batch.clear()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class LastUpdatedAt:
|
|
109
|
+
def __init__(self) -> None:
|
|
110
|
+
self._cache: DefaultDict[
|
|
111
|
+
Type[models.Base],
|
|
112
|
+
LRUCache[int, datetime],
|
|
113
|
+
] = defaultdict(lambda: LRUCache(maxsize=100))
|
|
114
|
+
|
|
115
|
+
def get(self, table: Type[models.Base], id_: Optional[int] = None) -> Optional[datetime]:
|
|
116
|
+
if not (cache := self._cache.get(table)):
|
|
117
|
+
return None
|
|
118
|
+
if id_ is None:
|
|
119
|
+
return max(filter(bool, cache.values()), default=None)
|
|
120
|
+
return cache.get(id_)
|
|
121
|
+
|
|
122
|
+
def set(self, table: Type[models.Base], id_: int) -> None:
|
|
123
|
+
self._cache[table][id_] = datetime.now(timezone.utc)
|
phoenix/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "4.20.
|
|
1
|
+
__version__ = "4.20.2"
|
phoenix/db/migrations/types.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
|
|
3
|
-
from sqlalchemy import JSON
|
|
4
|
-
from sqlalchemy.dialects import postgresql
|
|
5
|
-
from sqlalchemy.ext.compiler import compiles
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class JSONB(JSON):
|
|
9
|
-
# See https://docs.sqlalchemy.org/en/20/core/custom_types.html
|
|
10
|
-
__visit_name__ = "JSONB"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@compiles(JSONB, "sqlite") # type: ignore
|
|
14
|
-
def _(*args: Any, **kwargs: Any) -> str:
|
|
15
|
-
# See https://docs.sqlalchemy.org/en/20/core/custom_types.html
|
|
16
|
-
return "JSONB"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
JSON_ = (
|
|
20
|
-
JSON()
|
|
21
|
-
.with_variant(
|
|
22
|
-
postgresql.JSONB(), # type: ignore
|
|
23
|
-
"postgresql",
|
|
24
|
-
)
|
|
25
|
-
.with_variant(
|
|
26
|
-
JSONB(),
|
|
27
|
-
"sqlite",
|
|
28
|
-
)
|
|
29
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|