arize-phoenix 3.9.0__py3-none-any.whl → 3.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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: arize-phoenix
3
- Version: 3.9.0
3
+ Version: 3.10.0
4
4
  Summary: ML Observability in your notebook
5
5
  Project-URL: Documentation, https://docs.arize.com/phoenix/
6
6
  Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
@@ -1,10 +1,10 @@
1
1
  phoenix/__init__.py,sha256=mrgR7rvpc7LnBeyLzCX9wmRP4kJSJdfKDbj2zDiDjG8,2311
2
- phoenix/config.py,sha256=RT4UR5VH8JUAKQhfmlkpxq2kmBSA8G8MODrC3GXWyaI,3507
2
+ phoenix/config.py,sha256=sec_E60Dc2jFMouomk7I_0gitjs1AHU6yb-8Wcs7sTI,3740
3
3
  phoenix/datetime_utils.py,sha256=D955QLrkgrrSdUM6NyqbCeAu2SMsjhR5rHVQEsVUdng,2773
4
4
  phoenix/exceptions.py,sha256=X5k9ipUDfwSCwZB-H5zFJLas86Gf9tAx0W4l5TZxp5k,108
5
5
  phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
6
  phoenix/services.py,sha256=f6AeyKTuOpy9RCcTCjVH3gx5nYZhbTMFOuv1WSUOB5o,4992
7
- phoenix/version.py,sha256=ya3Avm9qHzetIgZApSM6eHjyO1KYOqbRf5xjSmbIqdg,22
7
+ phoenix/version.py,sha256=iKJAvc5i0UTDDSSefTGL0Tq-kWQ4S3OJJgvyaQfQNF8,23
8
8
  phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
10
10
  phoenix/core/model.py,sha256=C-kDATyJEgP-oqYVKOiQM76Ljs66F6VZdT93_b8kTGk,4725
@@ -62,7 +62,7 @@ phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
62
62
  phoenix/server/api/context.py,sha256=wjCzq4QlszKG1iN-xgu5rRLYPqdvTFqX02aFYPipNoQ,512
63
63
  phoenix/server/api/helpers.py,sha256=_V1eVkchZmTkhOfRC4QqR1sUB2xtIxdsMJkDouZq_IE,251
64
64
  phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
65
- phoenix/server/api/schema.py,sha256=3RUyezJizVLU4PPAS-W6fLVvJpDVfN48-Zp1vATwzKQ,14830
65
+ phoenix/server/api/schema.py,sha256=wYwmxM9tqZVd4OK8KN3KusVibThjaC4YSC-GnBlO-TY,7969
66
66
  phoenix/server/api/input_types/ClusterInput.py,sha256=EL4ftvZxQ8mVdruUPcdhMhByORmSmM8S-X6RPqU6GX0,179
67
67
  phoenix/server/api/input_types/Coordinates.py,sha256=meTwbIjwTfqx5DGD2DBlH9wQzdQVNM5a8x9dp1FfIgA,173
68
68
  phoenix/server/api/input_types/DataQualityMetricInput.py,sha256=LazvmQCCM5m9SDZTpyxQXO1rYF4cmsc3lsR2S9S65X4,1292
@@ -80,8 +80,7 @@ phoenix/server/api/routers/trace_handler.py,sha256=Ig601fM9AhJ-yhcj-w-PXo3cSCfVX
80
80
  phoenix/server/api/routers/utils.py,sha256=M41BoH-fl37izhRuN2aX7lWm7jOC20A_3uClv9TVUUY,583
81
81
  phoenix/server/api/types/Cluster.py,sha256=R08ZKrLl1KK8colxHU57N5XIOTMUwg5ZI50ofPoxxSM,5618
82
82
  phoenix/server/api/types/DataQualityMetric.py,sha256=zRKsNvHBu-NdcsunuLhqFpZhi6ks-HMqA1PJD27jTak,590
83
- phoenix/server/api/types/Dataset.py,sha256=sqfsJm10SSjXqTAfP8uoQV737hldU6Hj0lrH3KZFiSM,3102
84
- phoenix/server/api/types/DatasetInfo.py,sha256=tuSO2dvbrNZKwf-D5zRbCRJASuUvwqW-M8IK7-xf5bk,829
83
+ phoenix/server/api/types/Dataset.py,sha256=nQVtXltVfoKeccAQ5IHD_k1t5mCe8eIjD0nG-LZlhTk,3341
85
84
  phoenix/server/api/types/DatasetRole.py,sha256=UA8ecelVWfa9BVi--4A9fGhKFQ-jAaNHm7H5BpmZBPw,564
86
85
  phoenix/server/api/types/DatasetValues.py,sha256=7VbCOLlzOXpZN80-zYF2UGuafRcPsZF-8WQNc0YsKFc,1119
87
86
  phoenix/server/api/types/Dimension.py,sha256=IAS7Q7TkpbGqr1Vie4gJyi9SrYMK2L5mZwjYvpDQnQU,10198
@@ -104,7 +103,7 @@ phoenix/server/api/types/MimeType.py,sha256=VIUQBqveSctiRFStJjDUdZ85TeKhwNNEosMC
104
103
  phoenix/server/api/types/Model.py,sha256=IFhO2nouLQoMPNhl8vnm7nEXXSpr14CL3ihw8RnVWNY,7826
105
104
  phoenix/server/api/types/NumericRange.py,sha256=afEjgF97Go_OvmjMggbPBt-zGM8IONewAyEiKEHRds0,192
106
105
  phoenix/server/api/types/PerformanceMetric.py,sha256=W92B7OghEOgzFvmY0LCqpgavHaQggTGshdgfD0yqHX4,350
107
- phoenix/server/api/types/Project.py,sha256=ftJcJf3OAzx4-vcx9ZwRipHkqdFcnuqWVVBW750aeVE,7466
106
+ phoenix/server/api/types/Project.py,sha256=EArem8TsGV0PLUS_Vm-z45gY6syzcnJPlY1Iu0FI0eQ,8109
108
107
  phoenix/server/api/types/PromptResponse.py,sha256=Q8HKtpp8GpUOcxPCzZpkkokidDd6u0aZOv_SuPZZd5Q,630
109
108
  phoenix/server/api/types/Retrieval.py,sha256=OhMK2ncjoyp5h1yjKhjlKpoTbQrMHuxmgSFw-AO1rWw,285
110
109
  phoenix/server/api/types/ScalarDriftMetricEnum.py,sha256=IUAcRPpgL41WdoIgK6cNk2Te38SspXGyEs-S1fY23_A,232
@@ -128,15 +127,15 @@ phoenix/server/static/apple-touch-icon-76x76.png,sha256=CT_xT12I0u2i0WU8JzBZBuOQ
128
127
  phoenix/server/static/apple-touch-icon.png,sha256=fOfpjqGpWYbJ0eAurKsyoZP1EAs6ZVooBJ_SGk2ZkDs,3801
129
128
  phoenix/server/static/favicon.ico,sha256=bY0vvCKRftemZfPShwZtE93DiiQdaYaozkPGwNFr6H8,34494
130
129
  phoenix/server/static/index.css,sha256=KKGpx4iwF91VGRm0YN-4cn8oC-oIqC6HecoPf0x3ZM8,1885
131
- phoenix/server/static/index.js,sha256=5RUNHhzCAb0e0qTZSM1zn4O0UtXL1bxCTR--djZ7-ro,3171982
130
+ phoenix/server/static/index.js,sha256=NTBw2dg0KXyBdHg_1oGbpaKLD1kx1ZzGYMuMJpHIv2U,3175475
132
131
  phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_wcU9c,2564
133
132
  phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
134
133
  phoenix/server/templates/index.html,sha256=lO2wGA5XsftPg03rw_VcyaYf_4vegtlWbIT5ms4fA_c,1982
135
134
  phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
- phoenix/session/client.py,sha256=Lojylk8DLQzakNjMSoaEUmsntZeh8qgCZwsNQfXPbd4,5686
135
+ phoenix/session/client.py,sha256=9qlybwGGdPHql7n6Mye8feuh5_5AMq34xSajvcPn2yg,5853
137
136
  phoenix/session/data_extractor.py,sha256=0Kf-2mKY_YbYoD2fZkAYpKdFgsXrC3OKQ5d2iZsGgAI,1947
138
137
  phoenix/session/evaluation.py,sha256=YCv1XkWHi7vM_W5V7rorrrAxadv78wuMPeCVJvf5-oE,5444
139
- phoenix/session/session.py,sha256=hHgFUP6migoeWKUHio5IU03idcval55CX46heo5Dtn4,22169
138
+ phoenix/session/session.py,sha256=elU_198oGobkmbAL_nACpzBCYCnCaEbYgja00toU7mc,24472
140
139
  phoenix/trace/__init__.py,sha256=4d_MqzUIFmlY9WWcFeTONJ4xL5mPGoWZaPM2TJ0ZDBQ,266
141
140
  phoenix/trace/errors.py,sha256=wB1z8qdPckngdfU-TORToekvg3344oNFAA83_hC2yFY,180
142
141
  phoenix/trace/evaluation_conventions.py,sha256=t8jydM3U0-T5YpiQKRJ3tWdWGlHtzKyttYdw-ddvPOk,1048
@@ -156,20 +155,20 @@ phoenix/trace/dsl/helpers.py,sha256=CP6WaJpP7_WdI1Yoip7tDWcYDXZRg6xgNBRS2gojjMc,
156
155
  phoenix/trace/dsl/missing.py,sha256=BWPOHr2_tBkPDgVeq8GVXXVbNbJiBelu4NtwHBg6mTE,1435
157
156
  phoenix/trace/dsl/query.py,sha256=k0guhWBEo6L7ZJH5FJs2-iGSnWXdUUqu09gd-8M4CGg,14783
158
157
  phoenix/trace/langchain/__init__.py,sha256=aTKMFmEOgjx_6dnyplalgYi7PQnetablwrwpcUZqcGE,764
159
- phoenix/trace/langchain/instrumentor.py,sha256=rmqdaEh2rwyZnaddns4RC2WQnj7TbCnJjETgoiwWvzs,1163
158
+ phoenix/trace/langchain/instrumentor.py,sha256=95jtReVDtpymfK8eUGybevBJQWpbMnL9dg6XBgXmOQM,1420
160
159
  phoenix/trace/langchain/tracer.py,sha256=gq5RDgFexw-4qpwf701hGsZGcT6XdPjRIbI5aZdBI2I,1425
161
160
  phoenix/trace/llama_index/__init__.py,sha256=4fpR5702Qh2t5TaXIx584EkA-BveCPftXPOKvI0Oi3I,105
162
- phoenix/trace/llama_index/callback.py,sha256=YKCZZtFwAwasZt9qNSJO6dj97Jt2eN_PBakUYWrCleE,3574
161
+ phoenix/trace/llama_index/callback.py,sha256=EWHcg2IckOWMVUi1n1CmcDXRoMDoLTgGZ1LkqP2_fCg,4499
163
162
  phoenix/trace/openai/__init__.py,sha256=J3G0uqCxGdksUpaQVHds_Egv2drvh8UEqoLjiQAOveg,79
164
- phoenix/trace/openai/instrumentor.py,sha256=Lre96YfPxs5iM3frZfwdAh94LUpyYw_RZpSF0XmPtKw,1061
163
+ phoenix/trace/openai/instrumentor.py,sha256=OJGwuLXVChFmMcuojQrfBFsXvx4YsAsGhgwtgLfEX4c,1318
165
164
  phoenix/trace/v1/__init__.py,sha256=-IbAD0ruESMjvQLvGAg9CTfjBUATFDx1OXseDPis6-0,88
166
165
  phoenix/trace/v1/evaluation_pb2.py,sha256=8sXvv2BW_vqD30MOMbmkeE2zpmm7ncik21kl3e-HzeQ,2254
167
166
  phoenix/trace/v1/evaluation_pb2.pyi,sha256=cCbbx06gwQmaH14s3J1X25TtaARh-k1abbxQdQCXGm8,4500
168
167
  phoenix/utilities/__init__.py,sha256=8w1Ivw0KO9YKWrhcdnO73cSVqP9VHAp0pSfsi_oDiuQ,672
169
168
  phoenix/utilities/error_handling.py,sha256=7b5rpGFj9EWZ8yrZK1IHvxB89suWk3lggDayUQcvZds,1946
170
169
  phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,222
171
- arize_phoenix-3.9.0.dist-info/METADATA,sha256=RkO0IHCZHKQkP8RNPgHDiZ6CvIMT1E662qTykSz6OGw,29081
172
- arize_phoenix-3.9.0.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
173
- arize_phoenix-3.9.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
174
- arize_phoenix-3.9.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
175
- arize_phoenix-3.9.0.dist-info/RECORD,,
170
+ arize_phoenix-3.10.0.dist-info/METADATA,sha256=ZQfN5x4w8Pd7EdgjWDKFr_2JnQjl8MSr-ZpRx-OoeJ8,29082
171
+ arize_phoenix-3.10.0.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
172
+ arize_phoenix-3.10.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
173
+ arize_phoenix-3.10.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
174
+ arize_phoenix-3.10.0.dist-info/RECORD,,
phoenix/config.py CHANGED
@@ -17,6 +17,10 @@ ENV_PHOENIX_WORKING_DIR = "PHOENIX_WORKING_DIR"
17
17
  The directory in which to save, load, and export datasets. This directory must
18
18
  be accessible by both the Phoenix server and the notebook environment.
19
19
  """
20
+ ENV_PHOENIX_PROJECT_NAME = "PHOENIX_PROJECT_NAME"
21
+ """
22
+ The project name to use when logging traces and evals. defaults to 'default'.
23
+ """
20
24
 
21
25
 
22
26
  def _get_temp_path() -> Path:
@@ -113,3 +117,7 @@ def get_env_host() -> str:
113
117
 
114
118
  def get_env_collector_endpoint() -> Optional[str]:
115
119
  return os.getenv(ENV_PHOENIX_COLLECTOR_ENDPOINT)
120
+
121
+
122
+ def get_env_project_name() -> str:
123
+ return os.getenv(ENV_PHOENIX_PROJECT_NAME) or "default"
@@ -1,7 +1,5 @@
1
1
  from collections import defaultdict
2
- from datetime import datetime
3
- from itertools import chain
4
- from typing import Dict, List, Optional, Set, Tuple, Union, cast
2
+ from typing import Dict, List, Optional, Set, Union
5
3
 
6
4
  import numpy as np
7
5
  import numpy.typing as npt
@@ -10,7 +8,6 @@ from strawberry import ID, UNSET
10
8
  from strawberry.types import Info
11
9
  from typing_extensions import Annotated
12
10
 
13
- from phoenix.core.project import DEFAULT_PROJECT_NAME
14
11
  from phoenix.pointcloud.clustering import Hdbscan
15
12
  from phoenix.server.api.helpers import ensure_list
16
13
  from phoenix.server.api.input_types.ClusterInput import ClusterInput
@@ -18,15 +15,10 @@ from phoenix.server.api.input_types.Coordinates import (
18
15
  InputCoordinate2D,
19
16
  InputCoordinate3D,
20
17
  )
21
- from phoenix.server.api.input_types.SpanSort import SpanSort
22
18
  from phoenix.server.api.types.Cluster import Cluster, to_gql_clusters
23
19
  from phoenix.server.api.types.Project import Project
24
- from phoenix.trace.dsl import SpanFilter
25
- from phoenix.trace.schemas import SpanID, TraceID
26
20
 
27
21
  from .context import Context
28
- from .input_types.TimeRange import TimeRange
29
- from .types.DatasetInfo import TraceDatasetInfo
30
22
  from .types.DatasetRole import AncillaryDatasetRole, DatasetRole
31
23
  from .types.Dimension import to_gql_dimension
32
24
  from .types.EmbeddingDimension import (
@@ -35,15 +27,12 @@ from .types.EmbeddingDimension import (
35
27
  DEFAULT_MIN_SAMPLES,
36
28
  to_gql_embedding_dimension,
37
29
  )
38
- from .types.EvaluationSummary import EvaluationSummary
39
30
  from .types.Event import create_event_id, unpack_event_id
40
31
  from .types.ExportEventsMutation import ExportEventsMutation
41
32
  from .types.Functionality import Functionality
42
33
  from .types.Model import Model
43
34
  from .types.node import GlobalID, Node, from_global_id
44
35
  from .types.pagination import Connection, ConnectionArgs, Cursor, connection_from_list
45
- from .types.Span import Span, to_gql_span
46
- from .types.ValidationResult import ValidationResult
47
36
 
48
37
 
49
38
  @strawberry.type
@@ -233,190 +222,6 @@ class Query:
233
222
  clustered_events=clustered_events,
234
223
  )
235
224
 
236
- @strawberry.field
237
- def streaming_last_updated_at(
238
- self,
239
- info: Info[Context, None],
240
- ) -> Optional[datetime]:
241
- last_updated_at: Optional[datetime] = None
242
- if (traces := info.context.traces) is not None and (
243
- traces_last_updated_at := traces.last_updated_at
244
- ) is not None:
245
- last_updated_at = (
246
- traces_last_updated_at
247
- if last_updated_at is None
248
- else max(last_updated_at, traces_last_updated_at)
249
- )
250
- return last_updated_at
251
-
252
- @strawberry.field
253
- def spans(
254
- self,
255
- info: Info[Context, None],
256
- time_range: Optional[TimeRange] = UNSET,
257
- trace_ids: Optional[List[ID]] = UNSET,
258
- first: Optional[int] = 50,
259
- last: Optional[int] = UNSET,
260
- after: Optional[Cursor] = UNSET,
261
- before: Optional[Cursor] = UNSET,
262
- sort: Optional[SpanSort] = UNSET,
263
- root_spans_only: Optional[bool] = UNSET,
264
- filter_condition: Optional[str] = UNSET,
265
- ) -> Connection[Span]:
266
- args = ConnectionArgs(
267
- first=first,
268
- after=after if isinstance(after, Cursor) else None,
269
- last=last,
270
- before=before if isinstance(before, Cursor) else None,
271
- )
272
- if not (traces := info.context.traces) or not (
273
- project := traces.get_project(DEFAULT_PROJECT_NAME)
274
- ):
275
- return connection_from_list(data=[], args=args)
276
- predicate = (
277
- SpanFilter(
278
- condition=filter_condition,
279
- evals=project,
280
- )
281
- if filter_condition
282
- else None
283
- )
284
- if not trace_ids:
285
- spans = traces.get_spans(
286
- start_time=time_range.start if time_range else None,
287
- stop_time=time_range.end if time_range else None,
288
- root_spans_only=root_spans_only,
289
- )
290
- else:
291
- spans = chain.from_iterable(
292
- traces.get_trace(trace_id) for trace_id in map(TraceID, trace_ids)
293
- )
294
- if predicate:
295
- spans = filter(predicate, spans)
296
- if sort:
297
- spans = sort(spans, evals=project)
298
- data = list(map(to_gql_span, spans))
299
- return connection_from_list(data=data, args=args)
300
-
301
- @strawberry.field(
302
- description="Names of all available evaluations for spans. "
303
- "(The list contains no duplicates.)"
304
- ) # type: ignore
305
- def span_evaluation_names(
306
- self,
307
- info: Info[Context, None],
308
- ) -> List[str]:
309
- if not (traces := info.context.traces) or not (
310
- project := traces.get_project(DEFAULT_PROJECT_NAME)
311
- ):
312
- return []
313
- return project.get_span_evaluation_names()
314
-
315
- @strawberry.field(
316
- description="Names of available document evaluations.",
317
- ) # type: ignore
318
- def document_evaluation_names(
319
- self,
320
- info: Info[Context, None],
321
- span_id: Optional[ID] = UNSET,
322
- ) -> List[str]:
323
- if not (traces := info.context.traces) or not (
324
- project := traces.get_project(DEFAULT_PROJECT_NAME)
325
- ):
326
- return []
327
- return project.get_document_evaluation_names(
328
- None if span_id is UNSET else SpanID(span_id),
329
- )
330
-
331
- @strawberry.field
332
- def span_evaluation_summary(
333
- self,
334
- info: Info[Context, None],
335
- evaluation_name: str,
336
- time_range: Optional[TimeRange] = UNSET,
337
- filter_condition: Optional[str] = UNSET,
338
- ) -> Optional[EvaluationSummary]:
339
- if not (traces := info.context.traces) or not (
340
- project := traces.get_project(DEFAULT_PROJECT_NAME)
341
- ):
342
- return None
343
- predicate = (
344
- SpanFilter(
345
- condition=filter_condition,
346
- evals=project,
347
- )
348
- if filter_condition
349
- else None
350
- )
351
- span_ids = project.get_span_evaluation_span_ids(evaluation_name)
352
- if not span_ids:
353
- return None
354
- spans = traces.get_spans(
355
- start_time=time_range.start if time_range else None,
356
- stop_time=time_range.end if time_range else None,
357
- span_ids=span_ids,
358
- )
359
- if predicate:
360
- spans = filter(predicate, spans)
361
- evaluations = tuple(
362
- evaluation
363
- for span in spans
364
- if (
365
- evaluation := project.get_span_evaluation(
366
- span.context.span_id,
367
- evaluation_name,
368
- )
369
- )
370
- is not None
371
- )
372
- if not evaluations:
373
- return None
374
- labels = project.get_span_evaluation_labels(evaluation_name)
375
- return EvaluationSummary(evaluations, labels)
376
-
377
- @strawberry.field
378
- def trace_dataset_info(
379
- self,
380
- info: Info[Context, None],
381
- ) -> Optional[TraceDatasetInfo]:
382
- if (traces := info.context.traces) is None:
383
- return None
384
- if not (span_count := traces.span_count):
385
- return None
386
- start_time, stop_time = cast(
387
- Tuple[datetime, datetime],
388
- traces.right_open_time_range,
389
- )
390
- latency_ms_p50, latency_ms_p99 = traces.root_span_latency_ms_quantiles(0.50, 0.99)
391
- return TraceDatasetInfo(
392
- start_time=start_time,
393
- end_time=stop_time,
394
- record_count=span_count,
395
- token_count_total=traces.token_count_total,
396
- latency_ms_p50=latency_ms_p50,
397
- latency_ms_p99=latency_ms_p99,
398
- )
399
-
400
- @strawberry.field
401
- def validate_span_filter_condition(
402
- self, info: Info[Context, None], condition: str
403
- ) -> ValidationResult:
404
- traces = info.context.traces
405
- project = traces.get_project(DEFAULT_PROJECT_NAME) if traces else None
406
- valid_eval_names = project.get_span_evaluation_names() if project else ()
407
- try:
408
- SpanFilter(
409
- condition=condition,
410
- evals=project,
411
- valid_eval_names=valid_eval_names,
412
- )
413
- return ValidationResult(is_valid=True, error_message=None)
414
- except SyntaxError as e:
415
- return ValidationResult(
416
- is_valid=False,
417
- error_message=e.msg,
418
- )
419
-
420
225
 
421
226
  @strawberry.type
422
227
  class Mutation(ExportEventsMutation): ...
@@ -1,3 +1,4 @@
1
+ from datetime import datetime
1
2
  from typing import Iterable, List, Optional, Set, Union
2
3
 
3
4
  import strawberry
@@ -8,14 +9,16 @@ import phoenix.core.model_schema as ms
8
9
  from phoenix.core.model_schema import FEATURE, TAG, ScalarDimension
9
10
 
10
11
  from ..input_types.DimensionInput import DimensionInput
11
- from .DatasetInfo import DatasetInfo
12
12
  from .DatasetRole import AncillaryDatasetRole, DatasetRole
13
13
  from .Dimension import Dimension, to_gql_dimension
14
14
  from .Event import Event, create_event, create_event_id, parse_event_ids_by_dataset_role
15
15
 
16
16
 
17
17
  @strawberry.type
18
- class Dataset(DatasetInfo):
18
+ class Dataset:
19
+ start_time: datetime = strawberry.field(description="The start bookend of the data")
20
+ end_time: datetime = strawberry.field(description="The end bookend of the data")
21
+ record_count: int = strawberry.field(description="The record count of the data")
19
22
  dataset: strawberry.Private[ms.Dataset]
20
23
  dataset_role: strawberry.Private[Union[DatasetRole, AncillaryDatasetRole]]
21
24
  model: strawberry.Private[ms.Model]
@@ -19,6 +19,7 @@ from phoenix.server.api.types.pagination import (
19
19
  connection_from_list,
20
20
  )
21
21
  from phoenix.server.api.types.Span import Span, to_gql_span
22
+ from phoenix.server.api.types.ValidationResult import ValidationResult
22
23
  from phoenix.trace.dsl import SpanFilter
23
24
  from phoenix.trace.schemas import SpanID, TraceID
24
25
 
@@ -219,3 +220,19 @@ class Project(Node):
219
220
  self,
220
221
  ) -> Optional[datetime]:
221
222
  return self.project.last_updated_at
223
+
224
+ @strawberry.field
225
+ def validate_span_filter_condition(self, condition: str) -> ValidationResult:
226
+ valid_eval_names = self.project.get_span_evaluation_names()
227
+ try:
228
+ SpanFilter(
229
+ condition=condition,
230
+ evals=self.project,
231
+ valid_eval_names=valid_eval_names,
232
+ )
233
+ return ValidationResult(is_valid=True, error_message=None)
234
+ except SyntaxError as e:
235
+ return ValidationResult(
236
+ is_valid=False,
237
+ error_message=e.msg,
238
+ )