arize-phoenix 4.15.0__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.

Files changed (29) hide show
  1. {arize_phoenix-4.15.0.dist-info → arize_phoenix-4.16.0.dist-info}/METADATA +2 -1
  2. {arize_phoenix-4.15.0.dist-info → arize_phoenix-4.16.0.dist-info}/RECORD +29 -22
  3. phoenix/db/bulk_inserter.py +129 -2
  4. phoenix/db/helpers.py +23 -1
  5. phoenix/db/insertion/constants.py +2 -0
  6. phoenix/db/insertion/document_annotation.py +157 -0
  7. phoenix/db/insertion/helpers.py +13 -0
  8. phoenix/db/insertion/span_annotation.py +144 -0
  9. phoenix/db/insertion/trace_annotation.py +144 -0
  10. phoenix/db/insertion/types.py +261 -0
  11. phoenix/experiments/types.py +3 -3
  12. phoenix/server/api/input_types/SpanAnnotationSort.py +17 -0
  13. phoenix/server/api/input_types/TraceAnnotationSort.py +17 -0
  14. phoenix/server/api/routers/v1/evaluations.py +90 -4
  15. phoenix/server/api/routers/v1/spans.py +36 -46
  16. phoenix/server/api/routers/v1/traces.py +36 -48
  17. phoenix/server/api/types/Span.py +22 -3
  18. phoenix/server/api/types/Trace.py +21 -4
  19. phoenix/server/app.py +2 -0
  20. phoenix/server/static/.vite/manifest.json +14 -14
  21. phoenix/server/static/assets/{components-kGgeFkHp.js → components-Ci5kMOk5.js} +119 -126
  22. phoenix/server/static/assets/{index-BctFO6S7.js → index-BQG5WVX7.js} +2 -2
  23. phoenix/server/static/assets/{pages-DabDCmVd.js → pages-BrevprVW.js} +289 -213
  24. phoenix/server/static/assets/{vendor-arizeai-B5Hti8OB.js → vendor-arizeai-DTbiPGp6.js} +1 -1
  25. phoenix/trace/dsl/filter.py +2 -6
  26. phoenix/version.py +1 -1
  27. {arize_phoenix-4.15.0.dist-info → arize_phoenix-4.16.0.dist-info}/WHEEL +0 -0
  28. {arize_phoenix-4.15.0.dist-info → arize_phoenix-4.16.0.dist-info}/licenses/IP_NOTICE +0 -0
  29. {arize_phoenix-4.15.0.dist-info → arize_phoenix-4.16.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  import gzip
2
2
  from itertools import chain
3
- from typing import Iterator, Optional, Tuple
3
+ from typing import Any, Callable, Iterator, Optional, Tuple, Union, cast
4
4
 
5
5
  import pandas as pd
6
6
  import pyarrow as pa
@@ -24,10 +24,10 @@ from typing_extensions import TypeAlias
24
24
  import phoenix.trace.v1 as pb
25
25
  from phoenix.config import DEFAULT_PROJECT_NAME
26
26
  from phoenix.db import models
27
+ from phoenix.db.insertion.types import Precursors
27
28
  from phoenix.exceptions import PhoenixEvaluationNameIsMissing
28
29
  from phoenix.server.api.routers.utils import table_to_bytes
29
30
  from phoenix.server.types import DbSessionFactory
30
- from phoenix.session.evaluation import encode_evaluations
31
31
  from phoenix.trace.span_evaluations import (
32
32
  DocumentEvaluations,
33
33
  Evaluations,
@@ -194,8 +194,94 @@ async def _process_pyarrow(request: Request) -> Response:
194
194
 
195
195
 
196
196
  async def _add_evaluations(state: State, evaluations: Evaluations) -> None:
197
- for evaluation in encode_evaluations(evaluations):
198
- await state.queue_evaluation_for_bulk_insert(evaluation)
197
+ dataframe = evaluations.dataframe
198
+ eval_name = evaluations.eval_name
199
+ names = dataframe.index.names
200
+ if (
201
+ len(names) == 2
202
+ and "document_position" in names
203
+ and ("context.span_id" in names or "span_id" in names)
204
+ ):
205
+ cls = _document_annotation_factory(
206
+ names.index("span_id") if "span_id" in names else names.index("context.span_id"),
207
+ names.index("document_position"),
208
+ )
209
+ for index, row in dataframe.iterrows():
210
+ score, label, explanation = _get_annotation_result(row)
211
+ document_annotation = cls(cast(Union[Tuple[str, int], Tuple[int, str]], index))(
212
+ name=eval_name,
213
+ annotator_kind="LLM",
214
+ score=score,
215
+ label=label,
216
+ explanation=explanation,
217
+ metadata_={},
218
+ )
219
+ await state.enqueue(document_annotation)
220
+ elif len(names) == 1 and names[0] in ("context.span_id", "span_id"):
221
+ for index, row in dataframe.iterrows():
222
+ score, label, explanation = _get_annotation_result(row)
223
+ span_annotation = _span_annotation_factory(cast(str, index))(
224
+ name=eval_name,
225
+ annotator_kind="LLM",
226
+ score=score,
227
+ label=label,
228
+ explanation=explanation,
229
+ metadata_={},
230
+ )
231
+ await state.enqueue(span_annotation)
232
+ elif len(names) == 1 and names[0] in ("context.trace_id", "trace_id"):
233
+ for index, row in dataframe.iterrows():
234
+ score, label, explanation = _get_annotation_result(row)
235
+ trace_annotation = _trace_annotation_factory(cast(str, index))(
236
+ name=eval_name,
237
+ annotator_kind="LLM",
238
+ score=score,
239
+ label=label,
240
+ explanation=explanation,
241
+ metadata_={},
242
+ )
243
+ await state.enqueue(trace_annotation)
244
+
245
+
246
+ def _get_annotation_result(
247
+ row: "pd.Series[Any]",
248
+ ) -> Tuple[Optional[float], Optional[str], Optional[str]]:
249
+ return (
250
+ cast(Optional[float], row.get("score")),
251
+ cast(Optional[str], row.get("label")),
252
+ cast(Optional[str], row.get("explanation")),
253
+ )
254
+
255
+
256
+ def _document_annotation_factory(
257
+ span_id_idx: int,
258
+ document_position_idx: int,
259
+ ) -> Callable[
260
+ [Union[Tuple[str, int], Tuple[int, str]]],
261
+ Callable[..., Precursors.DocumentAnnotation],
262
+ ]:
263
+ return lambda index: lambda **kwargs: Precursors.DocumentAnnotation(
264
+ span_id=str(index[span_id_idx]),
265
+ document_position=int(index[document_position_idx]),
266
+ obj=models.DocumentAnnotation(
267
+ document_position=int(index[document_position_idx]),
268
+ **kwargs,
269
+ ),
270
+ )
271
+
272
+
273
+ def _span_annotation_factory(span_id: str) -> Callable[..., Precursors.SpanAnnotation]:
274
+ return lambda **kwargs: Precursors.SpanAnnotation(
275
+ span_id=str(span_id),
276
+ obj=models.SpanAnnotation(**kwargs),
277
+ )
278
+
279
+
280
+ def _trace_annotation_factory(trace_id: str) -> Callable[..., Precursors.TraceAnnotation]:
281
+ return lambda **kwargs: Precursors.TraceAnnotation(
282
+ trace_id=str(trace_id),
283
+ obj=models.TraceAnnotation(**kwargs),
284
+ )
199
285
 
200
286
 
201
287
  def _read_sql_trace_evaluations_into_dataframe(
@@ -13,9 +13,9 @@ from phoenix.config import DEFAULT_PROJECT_NAME
13
13
  from phoenix.datetime_utils import normalize_datetime
14
14
  from phoenix.db import models
15
15
  from phoenix.db.helpers import SupportedSQLDialect
16
- from phoenix.db.insertion.helpers import insert_on_conflict
16
+ from phoenix.db.insertion.helpers import as_kv, insert_on_conflict
17
+ from phoenix.db.insertion.types import Precursors
17
18
  from phoenix.server.api.routers.utils import df_to_bytes
18
- from phoenix.server.api.types.node import from_global_id_with_expected_type
19
19
  from phoenix.trace.dsl import SpanQuery as SpanQuery_
20
20
 
21
21
  from .pydantic_compat import V1RoutesBaseModel
@@ -143,7 +143,7 @@ class SpanAnnotationResult(V1RoutesBaseModel):
143
143
 
144
144
 
145
145
  class SpanAnnotation(V1RoutesBaseModel):
146
- span_id: str = Field(description="The ID of the span being annotated")
146
+ span_id: str = Field(description="OpenTelemetry Span ID (hex format w/o 0x prefix)")
147
147
  name: str = Field(description="The name of the annotation")
148
148
  annotator_kind: Literal["LLM", "HUMAN"] = Field(
149
149
  description="The kind of annotator used for the annotation"
@@ -155,6 +155,19 @@ class SpanAnnotation(V1RoutesBaseModel):
155
155
  default=None, description="Metadata for the annotation"
156
156
  )
157
157
 
158
+ def as_precursor(self) -> Precursors.SpanAnnotation:
159
+ return Precursors.SpanAnnotation(
160
+ self.span_id,
161
+ models.SpanAnnotation(
162
+ name=self.name,
163
+ annotator_kind=self.annotator_kind,
164
+ score=self.result.score if self.result else None,
165
+ label=self.result.label if self.result else None,
166
+ explanation=self.result.explanation if self.result else None,
167
+ metadata_=self.metadata or {},
168
+ ),
169
+ )
170
+
158
171
 
159
172
  class AnnotateSpansRequestBody(RequestBody[List[SpanAnnotation]]):
160
173
  data: List[SpanAnnotation]
@@ -178,59 +191,36 @@ class AnnotateSpansResponseBody(ResponseBody[List[InsertedSpanAnnotation]]):
178
191
  response_description="Span annotations inserted successfully",
179
192
  )
180
193
  async def annotate_spans(
181
- request: Request, request_body: AnnotateSpansRequestBody
194
+ request: Request,
195
+ request_body: AnnotateSpansRequestBody,
196
+ sync: bool = Query(default=True, description="If true, fulfill request synchronously."),
182
197
  ) -> AnnotateSpansResponseBody:
183
- span_annotations = request_body.data
184
- span_gids = [GlobalID.from_id(annotation.span_id) for annotation in span_annotations]
185
-
186
- resolved_span_ids = []
187
- for span_gid in span_gids:
188
- try:
189
- resolved_span_ids.append(from_global_id_with_expected_type(span_gid, "Span"))
190
- except ValueError:
191
- raise HTTPException(
192
- detail="Span with ID {span_gid} does not exist",
193
- status_code=HTTP_404_NOT_FOUND,
194
- )
198
+ precursors = [d.as_precursor() for d in request_body.data]
199
+ if not sync:
200
+ await request.state.enqueue(*precursors)
201
+ return AnnotateSpansResponseBody(data=[])
195
202
 
203
+ span_ids = {p.span_id for p in precursors}
196
204
  async with request.app.state.db() as session:
197
- spans = await session.execute(
198
- select(models.Span).filter(models.Span.id.in_(resolved_span_ids))
199
- )
200
- existing_span_ids = {span.id for span in spans.scalars()}
205
+ existing_spans = {
206
+ span.span_id: span.id
207
+ async for span in await session.stream_scalars(
208
+ select(models.Span).filter(models.Span.span_id.in_(span_ids))
209
+ )
210
+ }
201
211
 
202
- missing_span_ids = set(resolved_span_ids) - existing_span_ids
212
+ missing_span_ids = span_ids - set(existing_spans.keys())
203
213
  if missing_span_ids:
204
- missing_span_gids = [
205
- str(GlobalID("Span", str(span_gid))) for span_gid in missing_span_ids
206
- ]
207
214
  raise HTTPException(
208
- detail=f"Spans with IDs {', '.join(missing_span_gids)} do not exist.",
215
+ detail=f"Spans with IDs {', '.join(missing_span_ids)} do not exist.",
209
216
  status_code=HTTP_404_NOT_FOUND,
210
217
  )
211
218
 
212
219
  inserted_annotations = []
213
- for annotation in span_annotations:
214
- span_gid = GlobalID.from_id(annotation.span_id)
215
- span_id = from_global_id_with_expected_type(span_gid, "Span")
216
- name = annotation.name
217
- annotator_kind = annotation.annotator_kind
218
- result = annotation.result
219
- label = result.label if result else None
220
- score = result.score if result else None
221
- explanation = result.explanation if result else None
222
- metadata = annotation.metadata or {}
223
-
224
- values = dict(
225
- span_rowid=span_id,
226
- name=name,
227
- label=label,
228
- score=score,
229
- explanation=explanation,
230
- annotator_kind=annotator_kind,
231
- metadata_=metadata,
232
- )
233
- dialect = SupportedSQLDialect(session.bind.dialect.name)
220
+
221
+ dialect = SupportedSQLDialect(session.bind.dialect.name)
222
+ for p in precursors:
223
+ values = dict(as_kv(p.as_insertable(existing_spans[p.span_id]).row))
234
224
  span_annotation_id = await session.scalar(
235
225
  insert_on_conflict(
236
226
  values,
@@ -2,7 +2,7 @@ import gzip
2
2
  import zlib
3
3
  from typing import Any, Dict, List, Literal, Optional
4
4
 
5
- from fastapi import APIRouter, BackgroundTasks, Header, HTTPException
5
+ from fastapi import APIRouter, BackgroundTasks, Header, HTTPException, Query
6
6
  from google.protobuf.message import DecodeError
7
7
  from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import (
8
8
  ExportTraceServiceRequest,
@@ -22,8 +22,8 @@ from strawberry.relay import GlobalID
22
22
 
23
23
  from phoenix.db import models
24
24
  from phoenix.db.helpers import SupportedSQLDialect
25
- from phoenix.db.insertion.helpers import insert_on_conflict
26
- from phoenix.server.api.types.node import from_global_id_with_expected_type
25
+ from phoenix.db.insertion.helpers import as_kv, insert_on_conflict
26
+ from phoenix.db.insertion.types import Precursors
27
27
  from phoenix.trace.otel import decode_otlp_span
28
28
  from phoenix.utilities.project import get_project_name
29
29
 
@@ -100,7 +100,7 @@ class TraceAnnotationResult(V1RoutesBaseModel):
100
100
 
101
101
 
102
102
  class TraceAnnotation(V1RoutesBaseModel):
103
- trace_id: str = Field(description="The ID of the trace being annotated")
103
+ trace_id: str = Field(description="OpenTelemetry Trace ID (hex format w/o 0x prefix)")
104
104
  name: str = Field(description="The name of the annotation")
105
105
  annotator_kind: Literal["LLM", "HUMAN"] = Field(
106
106
  description="The kind of annotator used for the annotation"
@@ -112,6 +112,19 @@ class TraceAnnotation(V1RoutesBaseModel):
112
112
  default=None, description="Metadata for the annotation"
113
113
  )
114
114
 
115
+ def as_precursor(self) -> Precursors.TraceAnnotation:
116
+ return Precursors.TraceAnnotation(
117
+ self.trace_id,
118
+ models.TraceAnnotation(
119
+ name=self.name,
120
+ annotator_kind=self.annotator_kind,
121
+ score=self.result.score if self.result else None,
122
+ label=self.result.label if self.result else None,
123
+ explanation=self.result.explanation if self.result else None,
124
+ metadata_=self.metadata or {},
125
+ ),
126
+ )
127
+
115
128
 
116
129
  class AnnotateTracesRequestBody(RequestBody[List[TraceAnnotation]]):
117
130
  data: List[TraceAnnotation] = Field(description="The trace annotations to be upserted")
@@ -134,61 +147,36 @@ class AnnotateTracesResponseBody(ResponseBody[List[InsertedTraceAnnotation]]):
134
147
  ),
135
148
  )
136
149
  async def annotate_traces(
137
- request: Request, request_body: AnnotateTracesRequestBody
150
+ request: Request,
151
+ request_body: AnnotateTracesRequestBody,
152
+ sync: bool = Query(default=True, description="If true, fulfill request synchronously."),
138
153
  ) -> AnnotateTracesResponseBody:
139
- trace_annotations = request_body.data
140
- trace_gids = [GlobalID.from_id(annotation.trace_id) for annotation in trace_annotations]
141
-
142
- resolved_trace_ids = []
143
- for trace_gid in trace_gids:
144
- try:
145
- resolved_trace_ids.append(from_global_id_with_expected_type(trace_gid, "Trace"))
146
- except ValueError:
147
- raise HTTPException(
148
- detail="Trace with ID {trace_gid} does not exist",
149
- status_code=HTTP_404_NOT_FOUND,
150
- )
154
+ precursors = [d.as_precursor() for d in request_body.data]
155
+ if not sync:
156
+ await request.state.enqueue(*precursors)
157
+ return AnnotateTracesResponseBody(data=[])
151
158
 
159
+ trace_ids = {p.trace_id for p in precursors}
152
160
  async with request.app.state.db() as session:
153
- traces = await session.execute(
154
- select(models.Trace).filter(models.Trace.id.in_(resolved_trace_ids))
155
- )
156
- existing_trace_ids = {trace.id for trace in traces.scalars()}
161
+ existing_traces = {
162
+ trace.trace_id: trace.id
163
+ async for trace in await session.stream_scalars(
164
+ select(models.Trace).filter(models.Trace.trace_id.in_(trace_ids))
165
+ )
166
+ }
157
167
 
158
- missing_trace_ids = set(resolved_trace_ids) - existing_trace_ids
168
+ missing_trace_ids = trace_ids - set(existing_traces.keys())
159
169
  if missing_trace_ids:
160
- missing_trace_gids = [
161
- str(GlobalID("Trace", str(trace_gid))) for trace_gid in missing_trace_ids
162
- ]
163
170
  raise HTTPException(
164
- detail=f"Traces with IDs {', '.join(missing_trace_gids)} do not exist.",
171
+ detail=f"Traces with IDs {', '.join(missing_trace_ids)} do not exist.",
165
172
  status_code=HTTP_404_NOT_FOUND,
166
173
  )
167
174
 
168
175
  inserted_annotations = []
169
176
 
170
- for annotation in trace_annotations:
171
- trace_gid = GlobalID.from_id(annotation.trace_id)
172
- trace_id = from_global_id_with_expected_type(trace_gid, "Trace")
173
-
174
- name = annotation.name
175
- annotator_kind = annotation.annotator_kind
176
- result = annotation.result
177
- label = result.label if result else None
178
- score = result.score if result else None
179
- explanation = result.explanation if result else None
180
- metadata = annotation.metadata or {}
181
-
182
- values = dict(
183
- trace_rowid=trace_id,
184
- name=name,
185
- label=label,
186
- score=score,
187
- explanation=explanation,
188
- annotator_kind=annotator_kind,
189
- metadata_=metadata,
190
- )
191
- dialect = SupportedSQLDialect(session.bind.dialect.name)
177
+ dialect = SupportedSQLDialect(session.bind.dialect.name)
178
+ for p in precursors:
179
+ values = dict(as_kv(p.as_insertable(existing_traces[p.trace_id]).row))
192
180
  trace_annotation_id = await session.scalar(
193
181
  insert_on_conflict(
194
182
  values,
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, List, Mapping, Optional, Sized, cast
7
7
  import numpy as np
8
8
  import strawberry
9
9
  from openinference.semconv.trace import EmbeddingAttributes, SpanAttributes
10
+ from sqlalchemy import select
10
11
  from strawberry import ID, UNSET
11
12
  from strawberry.relay import Node, NodeID
12
13
  from strawberry.types import Info
@@ -19,6 +20,9 @@ from phoenix.server.api.helpers.dataset_helpers import (
19
20
  get_dataset_example_input,
20
21
  get_dataset_example_output,
21
22
  )
23
+ from phoenix.server.api.input_types.SpanAnnotationSort import SpanAnnotationSort
24
+ from phoenix.server.api.types.SortDir import SortDir
25
+ from phoenix.server.api.types.SpanAnnotation import to_gql_span_annotation
22
26
  from phoenix.trace.attributes import get_attribute_value
23
27
 
24
28
  from .DocumentRetrievalMetrics import DocumentRetrievalMetrics
@@ -177,12 +181,27 @@ class Span(Node):
177
181
 
178
182
  @strawberry.field(
179
183
  description=(
180
- "Annotations of the span's parent span. This encompasses both "
184
+ "Annotations associated with the span. This encompasses both "
181
185
  "LLM and human annotations."
182
186
  )
183
187
  ) # type: ignore
184
- async def span_annotations(self, info: Info[Context, None]) -> List[SpanAnnotation]:
185
- return await info.context.data_loaders.span_annotations.load(self.id_attr)
188
+ async def span_annotations(
189
+ self,
190
+ info: Info[Context, None],
191
+ sort: Optional[SpanAnnotationSort] = UNSET,
192
+ ) -> List[SpanAnnotation]:
193
+ async with info.context.db() as session:
194
+ stmt = select(models.SpanAnnotation).filter_by(span_rowid=self.id_attr)
195
+ if sort:
196
+ sort_col = getattr(models.SpanAnnotation, sort.col.value)
197
+ if sort.dir is SortDir.desc:
198
+ stmt = stmt.order_by(sort_col.desc(), models.SpanAnnotation.id.desc())
199
+ else:
200
+ stmt = stmt.order_by(sort_col.asc(), models.SpanAnnotation.id.asc())
201
+ else:
202
+ stmt = stmt.order_by(models.SpanAnnotation.created_at.desc())
203
+ annotations = await session.scalars(stmt)
204
+ return [to_gql_span_annotation(annotation) for annotation in annotations]
186
205
 
187
206
  @strawberry.field(
188
207
  description="Evaluations of the documents associated with the span, e.g. "
@@ -11,13 +11,15 @@ from strawberry.types import Info
11
11
 
12
12
  from phoenix.db import models
13
13
  from phoenix.server.api.context import Context
14
- from phoenix.server.api.types.Evaluation import TraceEvaluation
14
+ from phoenix.server.api.input_types.TraceAnnotationSort import TraceAnnotationSort
15
15
  from phoenix.server.api.types.pagination import (
16
16
  ConnectionArgs,
17
17
  CursorString,
18
18
  connection_from_list,
19
19
  )
20
+ from phoenix.server.api.types.SortDir import SortDir
20
21
  from phoenix.server.api.types.Span import Span, to_gql_span
22
+ from phoenix.server.api.types.TraceAnnotation import TraceAnnotation, to_gql_trace_annotation
21
23
 
22
24
 
23
25
  @strawberry.type
@@ -62,6 +64,21 @@ class Trace(Node):
62
64
  data = [to_gql_span(span) async for span in spans]
63
65
  return connection_from_list(data=data, args=args)
64
66
 
65
- @strawberry.field(description="Evaluations associated with the trace") # type: ignore
66
- async def trace_evaluations(self, info: Info[Context, None]) -> List[TraceEvaluation]:
67
- return await info.context.data_loaders.trace_evaluations.load(self.id_attr)
67
+ @strawberry.field(description="Annotations associated with the trace.") # type: ignore
68
+ async def span_annotations(
69
+ self,
70
+ info: Info[Context, None],
71
+ sort: Optional[TraceAnnotationSort] = None,
72
+ ) -> List[TraceAnnotation]:
73
+ async with info.context.db() as session:
74
+ stmt = select(models.TraceAnnotation).filter_by(span_rowid=self.id_attr)
75
+ if sort:
76
+ sort_col = getattr(models.TraceAnnotation, sort.col.value)
77
+ if sort.dir is SortDir.desc:
78
+ stmt = stmt.order_by(sort_col.desc(), models.TraceAnnotation.id.desc())
79
+ else:
80
+ stmt = stmt.order_by(sort_col.asc(), models.TraceAnnotation.id.asc())
81
+ else:
82
+ stmt = stmt.order_by(models.TraceAnnotation.created_at.desc())
83
+ annotations = await session.scalars(stmt)
84
+ return [to_gql_trace_annotation(annotation) for annotation in annotations]
phoenix/server/app.py CHANGED
@@ -229,6 +229,7 @@ def _lifespan(
229
229
  global DB_MUTEX
230
230
  DB_MUTEX = asyncio.Lock() if dialect is SupportedSQLDialect.SQLITE else None
231
231
  async with bulk_inserter as (
232
+ enqueue,
232
233
  queue_span,
233
234
  queue_evaluation,
234
235
  enqueue_operation,
@@ -239,6 +240,7 @@ def _lifespan(
239
240
  enable_prometheus=enable_prometheus,
240
241
  ):
241
242
  yield {
243
+ "enqueue": enqueue,
242
244
  "queue_span_for_bulk_insert": queue_span,
243
245
  "queue_evaluation_for_bulk_insert": queue_evaluation,
244
246
  "enqueue_operation": enqueue_operation,
@@ -1,22 +1,22 @@
1
1
  {
2
- "_components-kGgeFkHp.js": {
3
- "file": "assets/components-kGgeFkHp.js",
2
+ "_components-Ci5kMOk5.js": {
3
+ "file": "assets/components-Ci5kMOk5.js",
4
4
  "name": "components",
5
5
  "imports": [
6
6
  "_vendor-CP0b0YG0.js",
7
- "_vendor-arizeai-B5Hti8OB.js",
8
- "_pages-DabDCmVd.js",
7
+ "_vendor-arizeai-DTbiPGp6.js",
8
+ "_pages-BrevprVW.js",
9
9
  "_vendor-three-DwGkEfCM.js",
10
10
  "_vendor-codemirror-DtdPDzrv.js"
11
11
  ]
12
12
  },
13
- "_pages-DabDCmVd.js": {
14
- "file": "assets/pages-DabDCmVd.js",
13
+ "_pages-BrevprVW.js": {
14
+ "file": "assets/pages-BrevprVW.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
17
  "_vendor-CP0b0YG0.js",
18
- "_components-kGgeFkHp.js",
19
- "_vendor-arizeai-B5Hti8OB.js",
18
+ "_components-Ci5kMOk5.js",
19
+ "_vendor-arizeai-DTbiPGp6.js",
20
20
  "_vendor-recharts-A0DA1O99.js",
21
21
  "_vendor-codemirror-DtdPDzrv.js"
22
22
  ]
@@ -35,8 +35,8 @@
35
35
  "assets/vendor-DxkFTwjz.css"
36
36
  ]
37
37
  },
38
- "_vendor-arizeai-B5Hti8OB.js": {
39
- "file": "assets/vendor-arizeai-B5Hti8OB.js",
38
+ "_vendor-arizeai-DTbiPGp6.js": {
39
+ "file": "assets/vendor-arizeai-DTbiPGp6.js",
40
40
  "name": "vendor-arizeai",
41
41
  "imports": [
42
42
  "_vendor-CP0b0YG0.js"
@@ -61,15 +61,15 @@
61
61
  "name": "vendor-three"
62
62
  },
63
63
  "index.tsx": {
64
- "file": "assets/index-BctFO6S7.js",
64
+ "file": "assets/index-BQG5WVX7.js",
65
65
  "name": "index",
66
66
  "src": "index.tsx",
67
67
  "isEntry": true,
68
68
  "imports": [
69
69
  "_vendor-CP0b0YG0.js",
70
- "_vendor-arizeai-B5Hti8OB.js",
71
- "_pages-DabDCmVd.js",
72
- "_components-kGgeFkHp.js",
70
+ "_vendor-arizeai-DTbiPGp6.js",
71
+ "_pages-BrevprVW.js",
72
+ "_components-Ci5kMOk5.js",
73
73
  "_vendor-three-DwGkEfCM.js",
74
74
  "_vendor-recharts-A0DA1O99.js",
75
75
  "_vendor-codemirror-DtdPDzrv.js"