arize-phoenix 4.30.1__py3-none-any.whl → 4.30.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.30.1.dist-info → arize_phoenix-4.30.2.dist-info}/METADATA +1 -1
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.30.2.dist-info}/RECORD +13 -12
- phoenix/otel/otel.py +115 -6
- phoenix/server/api/context.py +2 -0
- phoenix/server/api/dataloaders/__init__.py +2 -0
- phoenix/server/api/dataloaders/dataset_example_revisions.py +54 -17
- phoenix/server/api/dataloaders/experiment_run_annotations.py +40 -0
- phoenix/server/api/types/ExperimentRun.py +1 -9
- phoenix/server/app.py +2 -0
- phoenix/version.py +1 -1
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.30.2.dist-info}/WHEEL +0 -0
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.30.2.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-4.30.1.dist-info → arize_phoenix-4.30.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,7 +6,7 @@ phoenix/exceptions.py,sha256=n2L2KKuecrdflB9MsCdAYCiSEvGJptIsfRkXMoJle7A,169
|
|
|
6
6
|
phoenix/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
7
|
phoenix/services.py,sha256=OyML4t2XGnlqF0JXA9_uccL8HslTABxep9Ci7MViKEU,5216
|
|
8
8
|
phoenix/settings.py,sha256=cO-qgis_S27nHirTobYI9hHPfZH18R--WMmxNdsVUwc,273
|
|
9
|
-
phoenix/version.py,sha256=
|
|
9
|
+
phoenix/version.py,sha256=DvmdNpuJDXvg0nMZADyqJJU0JkqI_2lJ8G7e_VN97L0,23
|
|
10
10
|
phoenix/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
phoenix/core/embedding_dimension.py,sha256=zKGbcvwOXgLf-yrJBpQyKtd-LEOPRKHnUToyAU8Owis,87
|
|
12
12
|
phoenix/core/model.py,sha256=km_a--PBHOuA337ClRw9xqhOHhrUT6Rl9pz_zV0JYkQ,4843
|
|
@@ -64,7 +64,7 @@ phoenix/metrics/retrieval_metrics.py,sha256=XFQPo66h16w7-1AJ92M1VL_BUIXIWxXHGKF_
|
|
|
64
64
|
phoenix/metrics/timeseries.py,sha256=Cib3E0njJzi0vZpmyADvbakFQA98rIkfDaYAOmsmBz8,6277
|
|
65
65
|
phoenix/metrics/wrappers.py,sha256=umZqa_5lf1wZSFe3FgzxF-qp1xbPdKD54W628GlGCUI,8392
|
|
66
66
|
phoenix/otel/__init__.py,sha256=YvEiD-3aGZs9agwLNCXU34ofV3G-Q-dolfsiinOJuT0,407
|
|
67
|
-
phoenix/otel/otel.py,sha256=
|
|
67
|
+
phoenix/otel/otel.py,sha256=NMQ-5KtpfCVGVkRzcz7fBsjCFTTR7R7wHna-87gvxfQ,17065
|
|
68
68
|
phoenix/otel/settings.py,sha256=Qr2-RkgLQRfLhJqtLpEkSpqns7qLjPoOvpEOTqeSohM,3026
|
|
69
69
|
phoenix/pointcloud/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
70
70
|
phoenix/pointcloud/clustering.py,sha256=IzcG67kJ2hPP7pcqVmKPSL_6gKRonKdOT3bCtbTOqnk,820
|
|
@@ -72,7 +72,7 @@ phoenix/pointcloud/pointcloud.py,sha256=4zAIkKs2xOUbchpj4XDAV-iPMXrfAJ15TG6rlIYG
|
|
|
72
72
|
phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcBYPU,1057
|
|
73
73
|
phoenix/pointcloud/umap_parameters.py,sha256=3UQSjrysVOvq2V4KNpTMqNqNiK0BsTZnPBHWZ4fyJtQ,1708
|
|
74
74
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
phoenix/server/app.py,sha256=
|
|
75
|
+
phoenix/server/app.py,sha256=4EPqxjfhFqxzk_JS560Gm8O9_TFtJ6lXW-72CfEzyGU,26920
|
|
76
76
|
phoenix/server/dml_event.py,sha256=MpjCFqljxvgb9OB5Cez9vJesb3oHb3XxXictynBfcis,2851
|
|
77
77
|
phoenix/server/dml_event_handler.py,sha256=6p-PucctivelVHfO-_9zNxWZYPr_eGjDF3bKjLtc5co,8251
|
|
78
78
|
phoenix/server/grpc_server.py,sha256=jllxDNkpLQxDkvej4RhTokobowbvydF-SU8gSw1MTCc,3378
|
|
@@ -82,22 +82,23 @@ phoenix/server/telemetry.py,sha256=T_2OKrxNViAeaANlNspEekg_Y5uZIFWvKAnpz8Aoqvk,2
|
|
|
82
82
|
phoenix/server/thread_server.py,sha256=RwXQGP_QhGD7le6WB7xEygEEuwBl5Ck_Zo8xGIYGi9M,2135
|
|
83
83
|
phoenix/server/types.py,sha256=S2dReLNboR2nzjRK5j3MUyUDqu6AQFD7KRwJkeKj1q4,3609
|
|
84
84
|
phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
85
|
-
phoenix/server/api/context.py,sha256=
|
|
85
|
+
phoenix/server/api/context.py,sha256=XLlRtIhBl3iEq7exrN_DaO0n-XyvuvdO5bLB4uDrQhI,3724
|
|
86
86
|
phoenix/server/api/exceptions.py,sha256=KdAzgwNan-wQ7THDrSoeJU2k9zWQVcH6lRiB462VsRA,990
|
|
87
87
|
phoenix/server/api/interceptor.py,sha256=ykDnoC_apUd-llVli3m1CW18kNSIgjz2qZ6m5JmPDu8,1294
|
|
88
88
|
phoenix/server/api/queries.py,sha256=hUzeHOUWuBQ-kjXh13-d5LgJfkbB8XSpFaHJX4YXpC8,23875
|
|
89
89
|
phoenix/server/api/schema.py,sha256=4L2m6QXhaV13YPTZCEZ3hqCPQFHZOy3QnJVLRYQFzpg,548
|
|
90
90
|
phoenix/server/api/utils.py,sha256=Kl47G-1A7QKTDrc75BU2QK6HupsG6MWuXxy351FOfKQ,858
|
|
91
|
-
phoenix/server/api/dataloaders/__init__.py,sha256=
|
|
91
|
+
phoenix/server/api/dataloaders/__init__.py,sha256=D1xEKunv8ZUBEPk2eStX-JhoPR3_NaQcNOp47H-oChM,3161
|
|
92
92
|
phoenix/server/api/dataloaders/annotation_summaries.py,sha256=Wv8AORZoGd5TJ4Y-em8iqJu87AMpZP7lWOTr-SML-x8,5560
|
|
93
93
|
phoenix/server/api/dataloaders/average_experiment_run_latency.py,sha256=q091UmkXx37OBKh7L-GJ5LXHyRXfX2w4XTk1NMHtPpw,1827
|
|
94
|
-
phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=
|
|
94
|
+
phoenix/server/api/dataloaders/dataset_example_revisions.py,sha256=_X2CwCc6lAkD4VuwAiyo4DfSVS8uuzub05sKyKiEXm8,5149
|
|
95
95
|
phoenix/server/api/dataloaders/dataset_example_spans.py,sha256=-TjdyyJv2c2JiN1OXu6MMmQ-BEKlHXucEDcuObeRVsU,1416
|
|
96
96
|
phoenix/server/api/dataloaders/document_evaluation_summaries.py,sha256=5XOom2KRAmCwPmtlraiZOSl3vhfaW-eiiYkmetAEalw,5616
|
|
97
97
|
phoenix/server/api/dataloaders/document_evaluations.py,sha256=V6sE34jON_qFxt7eArJbktykAsty-gnBZHlEkORcj0E,1296
|
|
98
98
|
phoenix/server/api/dataloaders/document_retrieval_metrics.py,sha256=JqDqkUuoeG6WfcmWSrmQptfF6IPX8XgzYzyECXTAjgg,4202
|
|
99
99
|
phoenix/server/api/dataloaders/experiment_annotation_summaries.py,sha256=qDEBRo0XKJMYBYlXBgJ-69jwPK-0r4pi9ZhbjC_vx6M,2813
|
|
100
100
|
phoenix/server/api/dataloaders/experiment_error_rates.py,sha256=wWTFOO2UxGIYUu53nnzzLk04-mJxw-BQgJELA9gT5bY,1949
|
|
101
|
+
phoenix/server/api/dataloaders/experiment_run_annotations.py,sha256=Ey42FYy6WIASWlO-KKwHewfvH_RBL0Ci3W3xrv4oyaE,1361
|
|
101
102
|
phoenix/server/api/dataloaders/experiment_run_counts.py,sha256=8VlKRaXwD56-7q_uonRr7L6QlEkyEQubkFKmKx6vuz0,1661
|
|
102
103
|
phoenix/server/api/dataloaders/experiment_sequence_number.py,sha256=hSpKyOz3ES4UTfOzOfHeQ1ZXat-bzcdKybVSbYmhrBw,1563
|
|
103
104
|
phoenix/server/api/dataloaders/latency_ms_quantile.py,sha256=5Y2OQ_GeH1My2573eOm7zPbqpwDZ_WeMLoZMq3KDoNQ,7403
|
|
@@ -198,7 +199,7 @@ phoenix/server/api/types/ExampleRevisionInterface.py,sha256=gV3Gt9-3Oi5wjaVtepC6
|
|
|
198
199
|
phoenix/server/api/types/Experiment.py,sha256=YNs8SzOMSYUKiAMANuWSv8NxSNFzSIFOBOWb_yztE0s,5482
|
|
199
200
|
phoenix/server/api/types/ExperimentAnnotationSummary.py,sha256=Uk3JtxIrsMoZT5tqc4nJdUOM3XegVzjUyoV3pkjNotE,256
|
|
200
201
|
phoenix/server/api/types/ExperimentComparison.py,sha256=0sFz6MoBDw39dds0qVyaqhVs9qqO5rkG1FMSjmfBeCc,441
|
|
201
|
-
phoenix/server/api/types/ExperimentRun.py,sha256=
|
|
202
|
+
phoenix/server/api/types/ExperimentRun.py,sha256=LkR7fBRZ3nH57ZoHJwePTGtJYcTMM-EH5r1TVPiMyxg,2687
|
|
202
203
|
phoenix/server/api/types/ExperimentRunAnnotation.py,sha256=iBxDaD9DgiF-Qymp5QyxWfJRGYXM1_CeWA_qzsZBqkI,1812
|
|
203
204
|
phoenix/server/api/types/ExportedFile.py,sha256=e3GTn7B5LgsTbqiwjhMCQH7VsiqXitrBO4aCMS1lHsg,163
|
|
204
205
|
phoenix/server/api/types/Functionality.py,sha256=tzV9xdhB8zqfsjWxP66NDC7EZsplYkYO7jRbLWJIeeg,382
|
|
@@ -295,8 +296,8 @@ phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,
|
|
|
295
296
|
phoenix/utilities/project.py,sha256=8IJuMM4yUMoooPi37sictGj8Etu9rGmq6RFtc9848cQ,436
|
|
296
297
|
phoenix/utilities/re.py,sha256=PDve_OLjRTM8yQQJHC8-n3HdIONi7aNils3ZKRZ5uBM,2045
|
|
297
298
|
phoenix/utilities/span_store.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
298
|
-
arize_phoenix-4.30.
|
|
299
|
-
arize_phoenix-4.30.
|
|
300
|
-
arize_phoenix-4.30.
|
|
301
|
-
arize_phoenix-4.30.
|
|
302
|
-
arize_phoenix-4.30.
|
|
299
|
+
arize_phoenix-4.30.2.dist-info/METADATA,sha256=qMHw9BdGbxXT2Z0TrtzXy-bv_atoD45Ohw0EF9pMu1k,11977
|
|
300
|
+
arize_phoenix-4.30.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
301
|
+
arize_phoenix-4.30.2.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
302
|
+
arize_phoenix-4.30.2.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
303
|
+
arize_phoenix-4.30.2.dist-info/RECORD,,
|
phoenix/otel/otel.py
CHANGED
|
@@ -51,9 +51,10 @@ def register(
|
|
|
51
51
|
not provided, the `PHOENIX_PROJECT_NAME` environment variable will be used.
|
|
52
52
|
batch (bool): If True, spans will be processed using a BatchSpanprocessor. If False, spans
|
|
53
53
|
will be processed one at a time using a SimpleSpanProcessor.
|
|
54
|
-
set_global_tracer_provider (bool): If False, the TracerProvider will not be set as the
|
|
55
|
-
tracer provider. Defaults to True.
|
|
56
|
-
headers (dict, optional): Optional headers to include in the
|
|
54
|
+
set_global_tracer_provider (bool): If False, the TracerProvider will not be set as the
|
|
55
|
+
global tracer provider. Defaults to True.
|
|
56
|
+
headers (dict, optional): Optional headers to include in the request to the collector.
|
|
57
|
+
If not provided, the `PHOENIX_CLIENT_HEADERS` environment variable will be used.
|
|
57
58
|
verbose (bool): If True, configuration details will be printed to stdout.
|
|
58
59
|
"""
|
|
59
60
|
|
|
@@ -73,7 +74,8 @@ def register(
|
|
|
73
74
|
global_provider_msg = (
|
|
74
75
|
"| \n"
|
|
75
76
|
"| `register` has set this TracerProvider as the global OpenTelemetry default.\n"
|
|
76
|
-
"| To disable this behavior, call `register` with
|
|
77
|
+
"| To disable this behavior, call `register` with "
|
|
78
|
+
"`set_global_tracer_provider=False`.\n"
|
|
77
79
|
)
|
|
78
80
|
else:
|
|
79
81
|
global_provider_msg = ""
|
|
@@ -85,6 +87,22 @@ def register(
|
|
|
85
87
|
|
|
86
88
|
|
|
87
89
|
class TracerProvider(_TracerProvider):
|
|
90
|
+
"""
|
|
91
|
+
An extension of `opentelemetry.sdk.trace.TracerProvider` with Phoenix-aware defaults.
|
|
92
|
+
|
|
93
|
+
Extended keyword arguments are documented in the `Args` section. For further documentation, see
|
|
94
|
+
the OpenTelemetry documentation at https://opentelemetry.io/docs/specs/otel/trace/sdk/.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
endpoint (str, optional): The collector endpoint to which spans will be exported. If
|
|
98
|
+
specified, a default SpanProcessor will be created and added to this TracerProvider.
|
|
99
|
+
If not provided, the `PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be
|
|
100
|
+
used to infer which collector endpoint to use, defaults to the gRPC endpoint. When
|
|
101
|
+
specifying the endpoint, the transport method (HTTP or gRPC) will be inferred from the
|
|
102
|
+
URL.
|
|
103
|
+
verbose (bool): If True, configuration details will be printed to stdout.
|
|
104
|
+
"""
|
|
105
|
+
|
|
88
106
|
def __init__(
|
|
89
107
|
self, *args: Any, endpoint: Optional[str] = None, verbose: bool = True, **kwargs: Any
|
|
90
108
|
):
|
|
@@ -112,6 +130,12 @@ class TracerProvider(_TracerProvider):
|
|
|
112
130
|
print(self._tracing_details())
|
|
113
131
|
|
|
114
132
|
def add_span_processor(self, *args: Any, **kwargs: Any) -> None:
|
|
133
|
+
"""
|
|
134
|
+
Registers a new `SpanProcessor` for this `TracerProvider`.
|
|
135
|
+
|
|
136
|
+
If this `TracerProvider` has a default processor, it will be removed.
|
|
137
|
+
"""
|
|
138
|
+
|
|
115
139
|
if self._default_processor:
|
|
116
140
|
self._active_span_processor.shutdown()
|
|
117
141
|
self._active_span_processor._span_processors = tuple() # remove default processors
|
|
@@ -163,6 +187,24 @@ class TracerProvider(_TracerProvider):
|
|
|
163
187
|
|
|
164
188
|
|
|
165
189
|
class SimpleSpanProcessor(_SimpleSpanProcessor):
|
|
190
|
+
"""
|
|
191
|
+
Simple SpanProcessor implementation.
|
|
192
|
+
|
|
193
|
+
SimpleSpanProcessor is an implementation of `SpanProcessor` that passes ended spans directly to
|
|
194
|
+
the configured `SpanExporter`.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
span_exporter (SpanExporter, optional): The `SpanExporter` to which ended spans will be
|
|
198
|
+
passed.
|
|
199
|
+
endpoint (str, optional): The collector endpoint to which spans will be exported. If not
|
|
200
|
+
provided, the `PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to
|
|
201
|
+
infer which collector endpoint to use, defaults to the gRPC endpoint. When specifying
|
|
202
|
+
the endpoint, the transport method (HTTP or gRPC) will be inferred from the URL.
|
|
203
|
+
headers (dict, optional): Optional headers to include in the request to the collector.
|
|
204
|
+
If not provided, the `PHOENIX_CLIENT_HEADERS` or `OTEL_EXPORTER_OTLP_HEADERS`
|
|
205
|
+
environment variable will be used.
|
|
206
|
+
"""
|
|
207
|
+
|
|
166
208
|
def __init__(
|
|
167
209
|
self,
|
|
168
210
|
span_exporter: Optional[SpanExporter] = None,
|
|
@@ -182,6 +224,37 @@ class SimpleSpanProcessor(_SimpleSpanProcessor):
|
|
|
182
224
|
|
|
183
225
|
|
|
184
226
|
class BatchSpanProcessor(_BatchSpanProcessor):
|
|
227
|
+
"""
|
|
228
|
+
Batch SpanProcessor implementation.
|
|
229
|
+
|
|
230
|
+
`BatchSpanProcessor` is an implementation of `SpanProcessor` that batches ended spans and
|
|
231
|
+
pushes them to the configured `SpanExporter`.
|
|
232
|
+
|
|
233
|
+
`BatchSpanProcessor` is configurable with the following environment variables which correspond
|
|
234
|
+
to constructor parameters:
|
|
235
|
+
|
|
236
|
+
- :envvar:`OTEL_BSP_SCHEDULE_DELAY`
|
|
237
|
+
- :envvar:`OTEL_BSP_MAX_QUEUE_SIZE`
|
|
238
|
+
- :envvar:`OTEL_BSP_MAX_EXPORT_BATCH_SIZE`
|
|
239
|
+
- :envvar:`OTEL_BSP_EXPORT_TIMEOUT`
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
span_exporter (SpanExporter, optional): The `SpanExporter` to which ended spans will be
|
|
243
|
+
passed.
|
|
244
|
+
endpoint (str, optional): The collector endpoint to which spans will be exported. If not
|
|
245
|
+
provided, the `PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to
|
|
246
|
+
infer which collector endpoint to use, defaults to the gRPC endpoint. When specifying
|
|
247
|
+
the endpoint, the transport method (HTTP or gRPC) will be inferred from the URL.
|
|
248
|
+
headers (dict, optional): Optional headers to include in the request to the collector.
|
|
249
|
+
If not provided, the `PHOENIX_CLIENT_HEADERS` or `OTEL_EXPORTER_OTLP_HEADERS`
|
|
250
|
+
environment variable will be used.
|
|
251
|
+
max_queue_size (int, optional): The maximum queue size.
|
|
252
|
+
schedule_delay_millis (float, optional): The delay between two consecutive exports in
|
|
253
|
+
milliseconds.
|
|
254
|
+
max_export_batch_size (int, optional): The maximum batch size.
|
|
255
|
+
export_timeout_millis (float, optional): The batch timeout in milliseconds.
|
|
256
|
+
"""
|
|
257
|
+
|
|
185
258
|
def __init__(
|
|
186
259
|
self,
|
|
187
260
|
span_exporter: Optional[SpanExporter] = None,
|
|
@@ -201,6 +274,20 @@ class BatchSpanProcessor(_BatchSpanProcessor):
|
|
|
201
274
|
|
|
202
275
|
|
|
203
276
|
class HTTPSpanExporter(_HTTPSpanExporter):
|
|
277
|
+
"""
|
|
278
|
+
OTLP span exporter using HTTP.
|
|
279
|
+
|
|
280
|
+
For more information, see:
|
|
281
|
+
- `opentelemetry.exporter.otlp.proto.http.trace_exporter.OTLPSpanExporter`
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
endpoint (str, optional): OpenTelemetry Collector receiver endpoint. If not provided, the
|
|
285
|
+
`PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to infer which
|
|
286
|
+
collector endpoint to use, defaults to the HTTP endpoint.
|
|
287
|
+
headers: Headers to send when exporting. If not provided, the `PHOENIX_CLIENT_HEADERS`
|
|
288
|
+
or `OTEL_EXPORTER_OTLP_HEADERS` environment variables will be used.
|
|
289
|
+
"""
|
|
290
|
+
|
|
204
291
|
def __init__(self, *args: Any, **kwargs: Any):
|
|
205
292
|
sig = inspect.signature(_HTTPSpanExporter)
|
|
206
293
|
bound_args = sig.bind_partial(*args, **kwargs)
|
|
@@ -210,12 +297,30 @@ class HTTPSpanExporter(_HTTPSpanExporter):
|
|
|
210
297
|
bound_args.arguments["headers"] = get_env_client_headers()
|
|
211
298
|
|
|
212
299
|
if bound_args.arguments.get("endpoint") is None:
|
|
213
|
-
_, endpoint = _normalized_endpoint(None)
|
|
300
|
+
_, endpoint = _normalized_endpoint(None, use_http=True)
|
|
214
301
|
bound_args.arguments["endpoint"] = endpoint
|
|
215
302
|
super().__init__(**bound_args.arguments)
|
|
216
303
|
|
|
217
304
|
|
|
218
305
|
class GRPCSpanExporter(_GRPCSpanExporter):
|
|
306
|
+
"""
|
|
307
|
+
OTLP span exporter using gRPC.
|
|
308
|
+
|
|
309
|
+
For more information, see:
|
|
310
|
+
- `opentelemetry.exporter.otlp.proto.grpc.trace_exporter.OTLPSpanExporter`
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
endpoint (str, optional): OpenTelemetry Collector receiver endpoint. If not provided, the
|
|
314
|
+
`PHOENIX_OTEL_COLLECTOR_ENDPOINT` environment variable will be used to infer which
|
|
315
|
+
collector endpoint to use, defaults to the gRPC endpoint.
|
|
316
|
+
insecure: Connection type
|
|
317
|
+
credentials: Credentials object for server authentication
|
|
318
|
+
headers: Headers to send when exporting. If not provided, the `PHOENIX_CLIENT_HEADERS`
|
|
319
|
+
or `OTEL_EXPORTER_OTLP_HEADERS` environment variables will be used.
|
|
320
|
+
timeout: Backend request timeout in seconds
|
|
321
|
+
compression: gRPC compression method to use
|
|
322
|
+
"""
|
|
323
|
+
|
|
219
324
|
def __init__(self, *args: Any, **kwargs: Any):
|
|
220
325
|
sig = inspect.signature(_GRPCSpanExporter)
|
|
221
326
|
bound_args = sig.bind_partial(*args, **kwargs)
|
|
@@ -270,12 +375,16 @@ _KNOWN_PROVIDERS = {
|
|
|
270
375
|
}
|
|
271
376
|
|
|
272
377
|
|
|
273
|
-
def _normalized_endpoint(
|
|
378
|
+
def _normalized_endpoint(
|
|
379
|
+
endpoint: Optional[str], use_http: bool = False
|
|
380
|
+
) -> Tuple[ParseResult, str]:
|
|
274
381
|
if endpoint is None:
|
|
275
382
|
base_endpoint = get_env_collector_endpoint() or "http://localhost:6006"
|
|
276
383
|
parsed = urlparse(base_endpoint)
|
|
277
384
|
if parsed.hostname in _KNOWN_PROVIDERS:
|
|
278
385
|
parsed = _KNOWN_PROVIDERS[parsed.hostname](parsed)
|
|
386
|
+
elif use_http:
|
|
387
|
+
parsed = _construct_http_endpoint(parsed)
|
|
279
388
|
else:
|
|
280
389
|
parsed = _construct_grpc_endpoint(parsed)
|
|
281
390
|
else:
|
phoenix/server/api/context.py
CHANGED
|
@@ -17,6 +17,7 @@ from phoenix.server.api.dataloaders import (
|
|
|
17
17
|
DocumentRetrievalMetricsDataLoader,
|
|
18
18
|
ExperimentAnnotationSummaryDataLoader,
|
|
19
19
|
ExperimentErrorRatesDataLoader,
|
|
20
|
+
ExperimentRunAnnotations,
|
|
20
21
|
ExperimentRunCountsDataLoader,
|
|
21
22
|
ExperimentSequenceNumberDataLoader,
|
|
22
23
|
LatencyMsQuantileDataLoader,
|
|
@@ -45,6 +46,7 @@ class DataLoaders:
|
|
|
45
46
|
annotation_summaries: AnnotationSummaryDataLoader
|
|
46
47
|
experiment_annotation_summaries: ExperimentAnnotationSummaryDataLoader
|
|
47
48
|
experiment_error_rates: ExperimentErrorRatesDataLoader
|
|
49
|
+
experiment_run_annotations: ExperimentRunAnnotations
|
|
48
50
|
experiment_run_counts: ExperimentRunCountsDataLoader
|
|
49
51
|
experiment_sequence_number: ExperimentSequenceNumberDataLoader
|
|
50
52
|
latency_ms_quantile: LatencyMsQuantileDataLoader
|
|
@@ -12,6 +12,7 @@ from .document_evaluations import DocumentEvaluationsDataLoader
|
|
|
12
12
|
from .document_retrieval_metrics import DocumentRetrievalMetricsDataLoader
|
|
13
13
|
from .experiment_annotation_summaries import ExperimentAnnotationSummaryDataLoader
|
|
14
14
|
from .experiment_error_rates import ExperimentErrorRatesDataLoader
|
|
15
|
+
from .experiment_run_annotations import ExperimentRunAnnotations
|
|
15
16
|
from .experiment_run_counts import ExperimentRunCountsDataLoader
|
|
16
17
|
from .experiment_sequence_number import ExperimentSequenceNumberDataLoader
|
|
17
18
|
from .latency_ms_quantile import LatencyMsQuantileCache, LatencyMsQuantileDataLoader
|
|
@@ -36,6 +37,7 @@ __all__ = [
|
|
|
36
37
|
"AnnotationSummaryDataLoader",
|
|
37
38
|
"ExperimentAnnotationSummaryDataLoader",
|
|
38
39
|
"ExperimentErrorRatesDataLoader",
|
|
40
|
+
"ExperimentRunAnnotations",
|
|
39
41
|
"ExperimentRunCountsDataLoader",
|
|
40
42
|
"ExperimentSequenceNumberDataLoader",
|
|
41
43
|
"LatencyMsQuantileDataLoader",
|
|
@@ -5,7 +5,8 @@ from typing import (
|
|
|
5
5
|
Union,
|
|
6
6
|
)
|
|
7
7
|
|
|
8
|
-
from sqlalchemy import
|
|
8
|
+
from sqlalchemy import and_, case, func, null, or_, select
|
|
9
|
+
from sqlalchemy.sql.expression import literal
|
|
9
10
|
from strawberry.dataloader import DataLoader
|
|
10
11
|
from typing_extensions import TypeAlias
|
|
11
12
|
|
|
@@ -22,40 +23,76 @@ Result: TypeAlias = DatasetExampleRevision
|
|
|
22
23
|
|
|
23
24
|
class DatasetExampleRevisionsDataLoader(DataLoader[Key, Result]):
|
|
24
25
|
def __init__(self, db: DbSessionFactory) -> None:
|
|
25
|
-
super().__init__(
|
|
26
|
+
super().__init__(
|
|
27
|
+
load_fn=self._load_fn,
|
|
28
|
+
max_batch_size=200, # needed to prevent the size of the query from getting too large
|
|
29
|
+
)
|
|
26
30
|
self._db = db
|
|
27
31
|
|
|
28
32
|
async def _load_fn(self, keys: List[Key]) -> List[Union[Result, NotFound]]:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
example_and_version_ids = tuple(
|
|
34
|
+
set(
|
|
35
|
+
(example_id, version_id)
|
|
36
|
+
for example_id, version_id in keys
|
|
37
|
+
if version_id is not None
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
versionless_example_ids = tuple(
|
|
41
|
+
set(example_id for example_id, version_id in keys if version_id is None)
|
|
42
|
+
)
|
|
43
|
+
resolved_example_and_version_ids = (
|
|
44
|
+
(
|
|
33
45
|
select(
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
models.DatasetExample.id.label("example_id"),
|
|
47
|
+
models.DatasetVersion.id.label("version_id"),
|
|
48
|
+
)
|
|
49
|
+
.select_from(models.DatasetExample)
|
|
50
|
+
.join(
|
|
51
|
+
models.DatasetVersion,
|
|
52
|
+
onclause=literal(True), # cross join
|
|
53
|
+
)
|
|
54
|
+
.where(
|
|
55
|
+
or_(
|
|
56
|
+
*(
|
|
57
|
+
and_(
|
|
58
|
+
models.DatasetExample.id == example_id,
|
|
59
|
+
models.DatasetVersion.id == version_id,
|
|
60
|
+
)
|
|
61
|
+
for example_id, version_id in example_and_version_ids
|
|
62
|
+
)
|
|
63
|
+
)
|
|
36
64
|
)
|
|
37
|
-
for example_id, version_id in keys
|
|
38
65
|
)
|
|
39
|
-
|
|
66
|
+
.union(
|
|
67
|
+
select(
|
|
68
|
+
models.DatasetExample.id.label("example_id"), null().label("version_id")
|
|
69
|
+
).where(models.DatasetExample.id.in_(versionless_example_ids))
|
|
70
|
+
)
|
|
71
|
+
.subquery()
|
|
72
|
+
)
|
|
40
73
|
revision_ids = (
|
|
41
74
|
select(
|
|
42
|
-
|
|
43
|
-
|
|
75
|
+
resolved_example_and_version_ids.c.example_id,
|
|
76
|
+
resolved_example_and_version_ids.c.version_id,
|
|
44
77
|
func.max(models.DatasetExampleRevision.id).label("revision_id"),
|
|
45
78
|
)
|
|
46
|
-
.select_from(
|
|
79
|
+
.select_from(resolved_example_and_version_ids)
|
|
47
80
|
.join(
|
|
48
81
|
models.DatasetExampleRevision,
|
|
49
|
-
onclause=
|
|
82
|
+
onclause=resolved_example_and_version_ids.c.example_id
|
|
50
83
|
== models.DatasetExampleRevision.dataset_example_id,
|
|
51
84
|
)
|
|
52
85
|
.where(
|
|
53
86
|
or_(
|
|
54
|
-
|
|
55
|
-
models.DatasetExampleRevision.dataset_version_id
|
|
87
|
+
resolved_example_and_version_ids.c.version_id.is_(None),
|
|
88
|
+
models.DatasetExampleRevision.dataset_version_id
|
|
89
|
+
<= resolved_example_and_version_ids.c.version_id,
|
|
56
90
|
)
|
|
57
91
|
)
|
|
58
|
-
.group_by(
|
|
92
|
+
.group_by(
|
|
93
|
+
resolved_example_and_version_ids.c.example_id,
|
|
94
|
+
resolved_example_and_version_ids.c.version_id,
|
|
95
|
+
)
|
|
59
96
|
).subquery()
|
|
60
97
|
query = (
|
|
61
98
|
select(
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from typing import (
|
|
3
|
+
DefaultDict,
|
|
4
|
+
List,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from sqlalchemy import select
|
|
8
|
+
from strawberry.dataloader import DataLoader
|
|
9
|
+
from typing_extensions import TypeAlias
|
|
10
|
+
|
|
11
|
+
from phoenix.db.models import ExperimentRunAnnotation as OrmExperimentRunAnnotation
|
|
12
|
+
from phoenix.server.types import DbSessionFactory
|
|
13
|
+
|
|
14
|
+
ExperimentRunID: TypeAlias = int
|
|
15
|
+
Key: TypeAlias = ExperimentRunID
|
|
16
|
+
Result: TypeAlias = List[OrmExperimentRunAnnotation]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ExperimentRunAnnotations(DataLoader[Key, Result]):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
db: DbSessionFactory,
|
|
23
|
+
) -> None:
|
|
24
|
+
super().__init__(load_fn=self._load_fn)
|
|
25
|
+
self._db = db
|
|
26
|
+
|
|
27
|
+
async def _load_fn(self, keys: List[Key]) -> List[Result]:
|
|
28
|
+
run_ids = tuple(set(keys))
|
|
29
|
+
annotations: DefaultDict[Key, Result] = defaultdict(list)
|
|
30
|
+
async with self._db() as session:
|
|
31
|
+
async for run_id, annotation in await session.stream(
|
|
32
|
+
select(
|
|
33
|
+
OrmExperimentRunAnnotation.experiment_run_id, OrmExperimentRunAnnotation
|
|
34
|
+
).where(OrmExperimentRunAnnotation.experiment_run_id.in_(run_ids))
|
|
35
|
+
):
|
|
36
|
+
annotations[run_id].append(annotation)
|
|
37
|
+
return [
|
|
38
|
+
sorted(annotations[run_id], key=lambda annotation: annotation.name, reverse=True)
|
|
39
|
+
for run_id in run_ids
|
|
40
|
+
]
|
|
@@ -2,7 +2,6 @@ from datetime import datetime
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
import strawberry
|
|
5
|
-
from sqlalchemy import select
|
|
6
5
|
from strawberry import UNSET
|
|
7
6
|
from strawberry.relay import Connection, GlobalID, Node, NodeID
|
|
8
7
|
from strawberry.scalars import JSON
|
|
@@ -48,14 +47,7 @@ class ExperimentRun(Node):
|
|
|
48
47
|
before=before if isinstance(before, CursorString) else None,
|
|
49
48
|
)
|
|
50
49
|
run_id = self.id_attr
|
|
51
|
-
|
|
52
|
-
annotations = (
|
|
53
|
-
await session.scalars(
|
|
54
|
-
select(models.ExperimentRunAnnotation)
|
|
55
|
-
.where(models.ExperimentRunAnnotation.experiment_run_id == run_id)
|
|
56
|
-
.order_by(models.ExperimentRunAnnotation.name.desc())
|
|
57
|
-
)
|
|
58
|
-
).all()
|
|
50
|
+
annotations = await info.context.data_loaders.experiment_run_annotations.load(run_id)
|
|
59
51
|
return connection_from_list(
|
|
60
52
|
[to_gql_experiment_run_annotation(annotation) for annotation in annotations], args
|
|
61
53
|
)
|
phoenix/server/app.py
CHANGED
|
@@ -66,6 +66,7 @@ from phoenix.server.api.dataloaders import (
|
|
|
66
66
|
DocumentRetrievalMetricsDataLoader,
|
|
67
67
|
ExperimentAnnotationSummaryDataLoader,
|
|
68
68
|
ExperimentErrorRatesDataLoader,
|
|
69
|
+
ExperimentRunAnnotations,
|
|
69
70
|
ExperimentRunCountsDataLoader,
|
|
70
71
|
ExperimentSequenceNumberDataLoader,
|
|
71
72
|
LatencyMsQuantileDataLoader,
|
|
@@ -446,6 +447,7 @@ def create_graphql_router(
|
|
|
446
447
|
),
|
|
447
448
|
experiment_annotation_summaries=ExperimentAnnotationSummaryDataLoader(db),
|
|
448
449
|
experiment_error_rates=ExperimentErrorRatesDataLoader(db),
|
|
450
|
+
experiment_run_annotations=ExperimentRunAnnotations(db),
|
|
449
451
|
experiment_run_counts=ExperimentRunCountsDataLoader(db),
|
|
450
452
|
experiment_sequence_number=ExperimentSequenceNumberDataLoader(db),
|
|
451
453
|
latency_ms_quantile=LatencyMsQuantileDataLoader(
|
phoenix/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "4.30.
|
|
1
|
+
__version__ = "4.30.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|