arize-phoenix 3.20.0__py3-none-any.whl → 3.22.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-3.20.0.dist-info → arize_phoenix-3.22.0.dist-info}/METADATA +7 -7
- {arize_phoenix-3.20.0.dist-info → arize_phoenix-3.22.0.dist-info}/RECORD +10 -10
- {arize_phoenix-3.20.0.dist-info → arize_phoenix-3.22.0.dist-info}/WHEEL +1 -1
- phoenix/inferences/inferences.py +207 -2
- phoenix/server/main.py +2 -2
- phoenix/session/client.py +40 -1
- phoenix/session/session.py +8 -8
- phoenix/version.py +1 -1
- {arize_phoenix-3.20.0.dist-info → arize_phoenix-3.22.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-3.20.0.dist-info → arize_phoenix-3.22.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: arize-phoenix
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.22.0
|
|
4
4
|
Summary: AI Observability and Evaluation
|
|
5
5
|
Project-URL: Documentation, https://docs.arize.com/phoenix/
|
|
6
6
|
Project-URL: Issues, https://github.com/Arize-ai/phoenix/issues
|
|
@@ -371,11 +371,11 @@ train_schema = px.Schema(
|
|
|
371
371
|
prod_schema = replace(train_schema, actual_label_column_name=None)
|
|
372
372
|
|
|
373
373
|
# Define your production and training datasets.
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
prod_inf = px.Inferences(prod_df, prod_schema)
|
|
375
|
+
train_inf = px.Inferences(train_df, train_schema)
|
|
376
376
|
|
|
377
377
|
# Launch Phoenix.
|
|
378
|
-
session = px.launch_app(
|
|
378
|
+
session = px.launch_app(prod_inf, train_inf)
|
|
379
379
|
|
|
380
380
|
# View the Phoenix UI in the browser
|
|
381
381
|
session.url
|
|
@@ -439,11 +439,11 @@ schema = px.Schema(
|
|
|
439
439
|
)
|
|
440
440
|
|
|
441
441
|
# Define your production and training datasets.
|
|
442
|
-
|
|
443
|
-
|
|
442
|
+
prod_inf = px.Inferences(dataframe=prod_df, schema=schema, name="production")
|
|
443
|
+
train_inf = px.Inferences(dataframe=train_df, schema=schema, name="training")
|
|
444
444
|
|
|
445
445
|
# Launch Phoenix for analysis
|
|
446
|
-
session = px.launch_app(primary=
|
|
446
|
+
session = px.launch_app(primary=prod_inf, reference=train_inf)
|
|
447
447
|
```
|
|
448
448
|
|
|
449
449
|
## Deploying Phoenix
|
|
@@ -4,7 +4,7 @@ phoenix/datetime_utils.py,sha256=D955QLrkgrrSdUM6NyqbCeAu2SMsjhR5rHVQEsVUdng,277
|
|
|
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=
|
|
7
|
+
phoenix/version.py,sha256=x3T39dw3H8eGDej-Y0jaguyUerrE7bTqWl_cTqwt5aM,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=SBO8BZg_CeQuH5LrSgzlQfqMModzirkQePdhnbLw7dE,4756
|
|
@@ -42,7 +42,7 @@ phoenix/experimental/evals/utils/threads.py,sha256=ksI-egarPnlxit0qKKjtjZ2L82qGL
|
|
|
42
42
|
phoenix/inferences/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
phoenix/inferences/errors.py,sha256=cGp9vxnw4SewFoWBV3ZGMkhE0Kh73lPIv3Ppz_H_RoA,8261
|
|
44
44
|
phoenix/inferences/fixtures.py,sha256=bEfvBixW56jje2Mrt4TH88V3N6K84XJX1HNFBZTh8PQ,20711
|
|
45
|
-
phoenix/inferences/inferences.py,sha256=
|
|
45
|
+
phoenix/inferences/inferences.py,sha256=6vtHq0exSQqy3IVGqvbgOPKfYMbgFgwmNG5YyZDsNuI,30694
|
|
46
46
|
phoenix/inferences/schema.py,sha256=UYej9IJ6pFeNW3fq721kJy16ONso_xVDm78Q68G4hl4,6643
|
|
47
47
|
phoenix/inferences/validation.py,sha256=dZ9lCFUV0EY7HCkQkQBrs-GLAEIZdpOqUxwD5l4dp88,8294
|
|
48
48
|
phoenix/metrics/README.md,sha256=5gekqTU-5gGdMwvcfNp2Wlu8p1ul9kGY_jq0XXQusoI,1964
|
|
@@ -60,7 +60,7 @@ phoenix/pointcloud/projectors.py,sha256=zO_RrtDYSv2rqVOfIP2_9Cv11Dc8EmcZR94xhFcB
|
|
|
60
60
|
phoenix/pointcloud/umap_parameters.py,sha256=lJsEOrbSuSiqI7g4Yt6xj7kgYxEqoep4ZHWLr6VWBqw,1760
|
|
61
61
|
phoenix/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
62
|
phoenix/server/app.py,sha256=eUw5tygCYmsQ5TAJTM_ZwRKkxDD3-bMJSH-H9YpF0eA,7246
|
|
63
|
-
phoenix/server/main.py,sha256=
|
|
63
|
+
phoenix/server/main.py,sha256=Su68-BSyN3wQm8od2TvT6iMOL84IvZdwtDCzsbMBmTk,9752
|
|
64
64
|
phoenix/server/prometheus.py,sha256=YQXwXZt3kxXN5JqGKDMH_jI9r4IL23xn6c8Bdrvg15A,2368
|
|
65
65
|
phoenix/server/thread_server.py,sha256=dP6cm6Cf08jNhDA1TRlVZpziu1YgtPDmaeIJMm725eI,2154
|
|
66
66
|
phoenix/server/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -138,10 +138,10 @@ phoenix/server/static/modernizr.js,sha256=mvK-XtkNqjOral-QvzoqsyOMECXIMu5BQwSVN_
|
|
|
138
138
|
phoenix/server/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
139
139
|
phoenix/server/templates/index.html,sha256=lO2wGA5XsftPg03rw_VcyaYf_4vegtlWbIT5ms4fA_c,1982
|
|
140
140
|
phoenix/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
141
|
-
phoenix/session/client.py,sha256=
|
|
141
|
+
phoenix/session/client.py,sha256=cYLRxV6YfCcWgZdJaStACVIhaN9j5p8S72tCKrT0RZ4,9612
|
|
142
142
|
phoenix/session/data_extractor.py,sha256=0Kf-2mKY_YbYoD2fZkAYpKdFgsXrC3OKQ5d2iZsGgAI,1947
|
|
143
143
|
phoenix/session/evaluation.py,sha256=mR5HeBDmoS9oCb-X-2lpLCyMRoOgBufofbsjyEqCpMg,5390
|
|
144
|
-
phoenix/session/session.py,sha256=
|
|
144
|
+
phoenix/session/session.py,sha256=P75qklh2HMgCCNiBghN3gjwRJiLIWzg1OshGt-fnzdM,24983
|
|
145
145
|
phoenix/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
146
146
|
phoenix/storage/span_store/__init__.py,sha256=ib-1BWPX4zMfIxS_qC-intyZciGMBJkAOcpb06d3jgQ,586
|
|
147
147
|
phoenix/storage/span_store/text_file.py,sha256=Fzpl_UDVN6_Qa8kpjhDkjdO7xb_I3g-UuTseenkV42c,2853
|
|
@@ -178,8 +178,8 @@ phoenix/utilities/error_handling.py,sha256=7b5rpGFj9EWZ8yrZK1IHvxB89suWk3lggDayU
|
|
|
178
178
|
phoenix/utilities/logging.py,sha256=lDXd6EGaamBNcQxL4vP1au9-i_SXe0OraUDiJOcszSw,222
|
|
179
179
|
phoenix/utilities/project.py,sha256=qWsvKnG1oKhOFUowXf9qiOL2ia7jaFe_ijFFHEt8GJo,431
|
|
180
180
|
phoenix/utilities/span_store.py,sha256=13UK0rE4wQd70yl___WsDRnH0ru-xErng9_Ml7zfEwE,978
|
|
181
|
-
arize_phoenix-3.
|
|
182
|
-
arize_phoenix-3.
|
|
183
|
-
arize_phoenix-3.
|
|
184
|
-
arize_phoenix-3.
|
|
185
|
-
arize_phoenix-3.
|
|
181
|
+
arize_phoenix-3.22.0.dist-info/METADATA,sha256=6Oog16HhrzCNfA5cS3JhS1OceuPvqiHL76Vzgz6hblE,29322
|
|
182
|
+
arize_phoenix-3.22.0.dist-info/WHEEL,sha256=K0BPUNF1N3kQ9olb8aVEtkObePEjdr2JOLT1N83EVws,87
|
|
183
|
+
arize_phoenix-3.22.0.dist-info/licenses/IP_NOTICE,sha256=JBqyyCYYxGDfzQ0TtsQgjts41IJoa-hiwDrBjCb9gHM,469
|
|
184
|
+
arize_phoenix-3.22.0.dist-info/licenses/LICENSE,sha256=HFkW9REuMOkvKRACuwLPT0hRydHb3zNg-fdFt94td18,3794
|
|
185
|
+
arize_phoenix-3.22.0.dist-info/RECORD,,
|
phoenix/inferences/inferences.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import re
|
|
2
3
|
import uuid
|
|
3
4
|
from copy import deepcopy
|
|
4
|
-
from dataclasses import fields, replace
|
|
5
|
+
from dataclasses import dataclass, fields, replace
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from itertools import groupby
|
|
5
8
|
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
6
9
|
|
|
7
10
|
import numpy as np
|
|
@@ -14,6 +17,7 @@ from typing_extensions import TypeAlias
|
|
|
14
17
|
|
|
15
18
|
from phoenix.config import DATASET_DIR, GENERATED_DATASET_NAME_PREFIX
|
|
16
19
|
from phoenix.datetime_utils import normalize_timestamps
|
|
20
|
+
from phoenix.utilities.deprecation import deprecated
|
|
17
21
|
|
|
18
22
|
from . import errors as err
|
|
19
23
|
from .schema import (
|
|
@@ -22,6 +26,7 @@ from .schema import (
|
|
|
22
26
|
SINGLE_COLUMN_SCHEMA_FIELD_NAMES,
|
|
23
27
|
EmbeddingColumnNames,
|
|
24
28
|
EmbeddingFeatures,
|
|
29
|
+
RetrievalEmbeddingColumnNames,
|
|
25
30
|
Schema,
|
|
26
31
|
SchemaFieldName,
|
|
27
32
|
SchemaFieldValue,
|
|
@@ -133,6 +138,206 @@ class Inferences:
|
|
|
133
138
|
with open(directory / self._schema_file_name, "w+") as schema_file:
|
|
134
139
|
schema_file.write(schema_json_data)
|
|
135
140
|
|
|
141
|
+
@classmethod
|
|
142
|
+
@deprecated("Inferences.from_open_inference is deprecated and will be removed.")
|
|
143
|
+
def from_open_inference(cls, dataframe: DataFrame) -> "Inferences":
|
|
144
|
+
schema = Schema()
|
|
145
|
+
column_renaming: Dict[str, str] = {}
|
|
146
|
+
for group_name, group in groupby(
|
|
147
|
+
sorted(
|
|
148
|
+
map(_parse_open_inference_column_name, dataframe.columns),
|
|
149
|
+
key=lambda column: column.name,
|
|
150
|
+
),
|
|
151
|
+
key=lambda column: column.name,
|
|
152
|
+
):
|
|
153
|
+
open_inference_columns = list(group)
|
|
154
|
+
if group_name == "":
|
|
155
|
+
column_names_by_category = {
|
|
156
|
+
column.category: column.full_name for column in open_inference_columns
|
|
157
|
+
}
|
|
158
|
+
schema = replace(
|
|
159
|
+
schema,
|
|
160
|
+
prediction_id_column_name=column_names_by_category.get(
|
|
161
|
+
OpenInferenceCategory.id
|
|
162
|
+
),
|
|
163
|
+
timestamp_column_name=column_names_by_category.get(
|
|
164
|
+
OpenInferenceCategory.timestamp
|
|
165
|
+
),
|
|
166
|
+
)
|
|
167
|
+
continue
|
|
168
|
+
column_names_by_specifier = {
|
|
169
|
+
column.specifier: column.full_name for column in open_inference_columns
|
|
170
|
+
}
|
|
171
|
+
if group_name == "response":
|
|
172
|
+
response_vector_column_name = column_names_by_specifier.get(
|
|
173
|
+
OpenInferenceSpecifier.embedding
|
|
174
|
+
)
|
|
175
|
+
if response_vector_column_name is not None:
|
|
176
|
+
column_renaming[response_vector_column_name] = "response"
|
|
177
|
+
schema = replace(
|
|
178
|
+
schema,
|
|
179
|
+
response_column_names=EmbeddingColumnNames(
|
|
180
|
+
vector_column_name=column_renaming[response_vector_column_name],
|
|
181
|
+
raw_data_column_name=column_names_by_specifier.get(
|
|
182
|
+
OpenInferenceSpecifier.default
|
|
183
|
+
),
|
|
184
|
+
),
|
|
185
|
+
)
|
|
186
|
+
else:
|
|
187
|
+
response_text_column_name = column_names_by_specifier.get(
|
|
188
|
+
OpenInferenceSpecifier.default
|
|
189
|
+
)
|
|
190
|
+
if response_text_column_name is None:
|
|
191
|
+
raise ValueError(
|
|
192
|
+
"invalid OpenInference format: missing text column for response"
|
|
193
|
+
)
|
|
194
|
+
column_renaming[response_text_column_name] = "response"
|
|
195
|
+
schema = replace(
|
|
196
|
+
schema,
|
|
197
|
+
response_column_names=column_renaming[response_text_column_name],
|
|
198
|
+
)
|
|
199
|
+
elif group_name == "prompt":
|
|
200
|
+
prompt_vector_column_name = column_names_by_specifier.get(
|
|
201
|
+
OpenInferenceSpecifier.embedding
|
|
202
|
+
)
|
|
203
|
+
if prompt_vector_column_name is None:
|
|
204
|
+
raise ValueError(
|
|
205
|
+
"invalid OpenInference format: missing embedding vector column for prompt"
|
|
206
|
+
)
|
|
207
|
+
column_renaming[prompt_vector_column_name] = "prompt"
|
|
208
|
+
schema = replace(
|
|
209
|
+
schema,
|
|
210
|
+
prompt_column_names=RetrievalEmbeddingColumnNames(
|
|
211
|
+
vector_column_name=column_renaming[prompt_vector_column_name],
|
|
212
|
+
raw_data_column_name=column_names_by_specifier.get(
|
|
213
|
+
OpenInferenceSpecifier.default
|
|
214
|
+
),
|
|
215
|
+
context_retrieval_ids_column_name=column_names_by_specifier.get(
|
|
216
|
+
OpenInferenceSpecifier.retrieved_document_ids
|
|
217
|
+
),
|
|
218
|
+
context_retrieval_scores_column_name=column_names_by_specifier.get(
|
|
219
|
+
OpenInferenceSpecifier.retrieved_document_scores
|
|
220
|
+
),
|
|
221
|
+
),
|
|
222
|
+
)
|
|
223
|
+
elif OpenInferenceSpecifier.embedding in column_names_by_specifier:
|
|
224
|
+
vector_column_name = column_names_by_specifier[OpenInferenceSpecifier.embedding]
|
|
225
|
+
column_renaming[vector_column_name] = group_name
|
|
226
|
+
embedding_feature_column_names = schema.embedding_feature_column_names or {}
|
|
227
|
+
embedding_feature_column_names.update(
|
|
228
|
+
{
|
|
229
|
+
group_name: EmbeddingColumnNames(
|
|
230
|
+
vector_column_name=column_renaming[vector_column_name],
|
|
231
|
+
raw_data_column_name=column_names_by_specifier.get(
|
|
232
|
+
OpenInferenceSpecifier.raw_data
|
|
233
|
+
),
|
|
234
|
+
link_to_data_column_name=column_names_by_specifier.get(
|
|
235
|
+
OpenInferenceSpecifier.link_to_data
|
|
236
|
+
),
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
)
|
|
240
|
+
schema = replace(
|
|
241
|
+
schema,
|
|
242
|
+
embedding_feature_column_names=embedding_feature_column_names,
|
|
243
|
+
)
|
|
244
|
+
elif len(open_inference_columns) == 1:
|
|
245
|
+
open_inference_column = open_inference_columns[0]
|
|
246
|
+
raw_column_name = open_inference_column.full_name
|
|
247
|
+
column_renaming[raw_column_name] = open_inference_column.name
|
|
248
|
+
if open_inference_column.category is OpenInferenceCategory.feature:
|
|
249
|
+
schema = replace(
|
|
250
|
+
schema,
|
|
251
|
+
feature_column_names=(
|
|
252
|
+
(schema.feature_column_names or []) + [column_renaming[raw_column_name]]
|
|
253
|
+
),
|
|
254
|
+
)
|
|
255
|
+
elif open_inference_column.category is OpenInferenceCategory.tag:
|
|
256
|
+
schema = replace(
|
|
257
|
+
schema,
|
|
258
|
+
tag_column_names=(
|
|
259
|
+
(schema.tag_column_names or []) + [column_renaming[raw_column_name]]
|
|
260
|
+
),
|
|
261
|
+
)
|
|
262
|
+
elif open_inference_column.category is OpenInferenceCategory.prediction:
|
|
263
|
+
if open_inference_column.specifier is OpenInferenceSpecifier.score:
|
|
264
|
+
schema = replace(
|
|
265
|
+
schema,
|
|
266
|
+
prediction_score_column_name=column_renaming[raw_column_name],
|
|
267
|
+
)
|
|
268
|
+
if open_inference_column.specifier is OpenInferenceSpecifier.label:
|
|
269
|
+
schema = replace(
|
|
270
|
+
schema,
|
|
271
|
+
prediction_label_column_name=column_renaming[raw_column_name],
|
|
272
|
+
)
|
|
273
|
+
elif open_inference_column.category is OpenInferenceCategory.actual:
|
|
274
|
+
if open_inference_column.specifier is OpenInferenceSpecifier.score:
|
|
275
|
+
schema = replace(
|
|
276
|
+
schema,
|
|
277
|
+
actual_score_column_name=column_renaming[raw_column_name],
|
|
278
|
+
)
|
|
279
|
+
if open_inference_column.specifier is OpenInferenceSpecifier.label:
|
|
280
|
+
schema = replace(
|
|
281
|
+
schema,
|
|
282
|
+
actual_label_column_name=column_renaming[raw_column_name],
|
|
283
|
+
)
|
|
284
|
+
else:
|
|
285
|
+
raise ValueError(f"invalid OpenInference format: duplicated name `{group_name}`")
|
|
286
|
+
|
|
287
|
+
return cls(
|
|
288
|
+
dataframe.rename(
|
|
289
|
+
column_renaming,
|
|
290
|
+
axis=1,
|
|
291
|
+
copy=False,
|
|
292
|
+
),
|
|
293
|
+
schema,
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class OpenInferenceCategory(Enum):
|
|
298
|
+
id = "id"
|
|
299
|
+
timestamp = "timestamp"
|
|
300
|
+
feature = "feature"
|
|
301
|
+
tag = "tag"
|
|
302
|
+
prediction = "prediction"
|
|
303
|
+
actual = "actual"
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class OpenInferenceSpecifier(Enum):
|
|
307
|
+
default = ""
|
|
308
|
+
score = "score"
|
|
309
|
+
label = "label"
|
|
310
|
+
embedding = "embedding"
|
|
311
|
+
raw_data = "raw_data"
|
|
312
|
+
link_to_data = "link_to_data"
|
|
313
|
+
retrieved_document_ids = "retrieved_document_ids"
|
|
314
|
+
retrieved_document_scores = "retrieved_document_scores"
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@dataclass(frozen=True)
|
|
318
|
+
class _OpenInferenceColumnName:
|
|
319
|
+
full_name: str
|
|
320
|
+
category: OpenInferenceCategory
|
|
321
|
+
data_type: str
|
|
322
|
+
specifier: OpenInferenceSpecifier = OpenInferenceSpecifier.default
|
|
323
|
+
name: str = ""
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _parse_open_inference_column_name(column_name: str) -> _OpenInferenceColumnName:
|
|
327
|
+
pattern = (
|
|
328
|
+
r"^:(?P<category>\w+)\.(?P<data_type>\[\w+\]|\w+)(\.(?P<specifier>\w+))?:(?P<name>.*)?$"
|
|
329
|
+
)
|
|
330
|
+
if match := re.match(pattern, column_name):
|
|
331
|
+
extract = match.groupdict(default="")
|
|
332
|
+
return _OpenInferenceColumnName(
|
|
333
|
+
full_name=column_name,
|
|
334
|
+
category=OpenInferenceCategory(extract.get("category", "").lower()),
|
|
335
|
+
data_type=extract.get("data_type", "").lower(),
|
|
336
|
+
specifier=OpenInferenceSpecifier(extract.get("specifier", "").lower()),
|
|
337
|
+
name=extract.get("name", ""),
|
|
338
|
+
)
|
|
339
|
+
raise ValueError(f"Invalid format for column name: {column_name}")
|
|
340
|
+
|
|
136
341
|
|
|
137
342
|
def _parse_dataframe_and_schema(dataframe: DataFrame, schema: Schema) -> Tuple[DataFrame, Schema]:
|
|
138
343
|
"""
|
|
@@ -522,4 +727,4 @@ def _add_prediction_id(num_rows: int) -> List[str]:
|
|
|
522
727
|
|
|
523
728
|
|
|
524
729
|
# A dataset with no data. Useful for stubs
|
|
525
|
-
|
|
730
|
+
EMPTY_INFERENCES = Inferences(pd.DataFrame(), schema=Schema())
|
phoenix/server/main.py
CHANGED
|
@@ -20,7 +20,7 @@ from phoenix.config import (
|
|
|
20
20
|
from phoenix.core.model_schema_adapter import create_model_from_datasets
|
|
21
21
|
from phoenix.core.traces import Traces
|
|
22
22
|
from phoenix.inferences.fixtures import FIXTURES, get_datasets
|
|
23
|
-
from phoenix.inferences.inferences import
|
|
23
|
+
from phoenix.inferences.inferences import EMPTY_INFERENCES, Inferences
|
|
24
24
|
from phoenix.pointcloud.umap_parameters import (
|
|
25
25
|
DEFAULT_MIN_DIST,
|
|
26
26
|
DEFAULT_N_NEIGHBORS,
|
|
@@ -114,7 +114,7 @@ if __name__ == "__main__":
|
|
|
114
114
|
trace_dataset_name: Optional[str] = None
|
|
115
115
|
simulate_streaming: Optional[bool] = None
|
|
116
116
|
|
|
117
|
-
primary_dataset: Inferences =
|
|
117
|
+
primary_dataset: Inferences = EMPTY_INFERENCES
|
|
118
118
|
reference_dataset: Optional[Inferences] = None
|
|
119
119
|
corpus_dataset: Optional[Inferences] = None
|
|
120
120
|
|
phoenix/session/client.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import gzip
|
|
1
2
|
import logging
|
|
2
3
|
import weakref
|
|
3
4
|
from datetime import datetime
|
|
@@ -7,6 +8,10 @@ from urllib.parse import urljoin
|
|
|
7
8
|
|
|
8
9
|
import pandas as pd
|
|
9
10
|
import pyarrow as pa
|
|
11
|
+
from opentelemetry.proto.collector.trace.v1.trace_service_pb2 import ExportTraceServiceRequest
|
|
12
|
+
from opentelemetry.proto.common.v1.common_pb2 import AnyValue, KeyValue
|
|
13
|
+
from opentelemetry.proto.resource.v1.resource_pb2 import Resource
|
|
14
|
+
from opentelemetry.proto.trace.v1.trace_pb2 import ResourceSpans, ScopeSpans
|
|
10
15
|
from pyarrow import ArrowInvalid
|
|
11
16
|
from requests import Session
|
|
12
17
|
|
|
@@ -18,8 +23,9 @@ from phoenix.config import (
|
|
|
18
23
|
get_env_project_name,
|
|
19
24
|
)
|
|
20
25
|
from phoenix.session.data_extractor import TraceDataExtractor
|
|
21
|
-
from phoenix.trace import Evaluations
|
|
26
|
+
from phoenix.trace import Evaluations, TraceDataset
|
|
22
27
|
from phoenix.trace.dsl import SpanQuery
|
|
28
|
+
from phoenix.trace.otel import encode
|
|
23
29
|
|
|
24
30
|
logger = logging.getLogger(__name__)
|
|
25
31
|
|
|
@@ -193,6 +199,39 @@ class Client(TraceDataExtractor):
|
|
|
193
199
|
headers=headers,
|
|
194
200
|
).raise_for_status()
|
|
195
201
|
|
|
202
|
+
def log_traces(self, trace_dataset: TraceDataset, project_name: Optional[str] = None) -> None:
|
|
203
|
+
project_name = project_name or get_env_project_name()
|
|
204
|
+
spans = trace_dataset.to_spans()
|
|
205
|
+
otlp_spans = [
|
|
206
|
+
ExportTraceServiceRequest(
|
|
207
|
+
resource_spans=[
|
|
208
|
+
ResourceSpans(
|
|
209
|
+
resource=Resource(
|
|
210
|
+
attributes=[
|
|
211
|
+
KeyValue(
|
|
212
|
+
key="openinference.project.name",
|
|
213
|
+
value=AnyValue(string_value=project_name),
|
|
214
|
+
)
|
|
215
|
+
]
|
|
216
|
+
),
|
|
217
|
+
scope_spans=[ScopeSpans(spans=[encode(span)])],
|
|
218
|
+
)
|
|
219
|
+
],
|
|
220
|
+
)
|
|
221
|
+
for span in spans
|
|
222
|
+
]
|
|
223
|
+
for otlp_span in otlp_spans:
|
|
224
|
+
serialized = otlp_span.SerializeToString()
|
|
225
|
+
data = gzip.compress(serialized)
|
|
226
|
+
self._session.post(
|
|
227
|
+
urljoin(self._base_url, "/v1/traces"),
|
|
228
|
+
data=data,
|
|
229
|
+
headers={
|
|
230
|
+
"content-type": "application/x-protobuf",
|
|
231
|
+
"content-encoding": "gzip",
|
|
232
|
+
},
|
|
233
|
+
).raise_for_status()
|
|
234
|
+
|
|
196
235
|
|
|
197
236
|
def _to_iso_format(value: Optional[datetime]) -> Optional[str]:
|
|
198
237
|
return value.isoformat() if value else None
|
phoenix/session/session.py
CHANGED
|
@@ -36,7 +36,7 @@ from phoenix.config import (
|
|
|
36
36
|
)
|
|
37
37
|
from phoenix.core.model_schema_adapter import create_model_from_datasets
|
|
38
38
|
from phoenix.core.traces import Traces
|
|
39
|
-
from phoenix.inferences.inferences import
|
|
39
|
+
from phoenix.inferences.inferences import EMPTY_INFERENCES, Inferences
|
|
40
40
|
from phoenix.pointcloud.umap_parameters import get_umap_parameters
|
|
41
41
|
from phoenix.server.app import create_app
|
|
42
42
|
from phoenix.server.thread_server import ThreadServer
|
|
@@ -473,17 +473,17 @@ def launch_app(
|
|
|
473
473
|
Examples
|
|
474
474
|
--------
|
|
475
475
|
>>> import phoenix as px
|
|
476
|
-
>>> # construct
|
|
477
|
-
>>>
|
|
478
|
-
>>> session = px.launch_app(
|
|
476
|
+
>>> # construct an inference set to analyze
|
|
477
|
+
>>> inferences = px.Inferences(...)
|
|
478
|
+
>>> session = px.launch_app(inferences)
|
|
479
479
|
"""
|
|
480
480
|
global _session
|
|
481
481
|
|
|
482
|
-
# Stopgap solution to allow the app to run without a primary
|
|
482
|
+
# Stopgap solution to allow the app to run without a primary inferences
|
|
483
483
|
if primary is None:
|
|
484
|
-
# Dummy
|
|
485
|
-
# TODO: pass through the lack of a primary
|
|
486
|
-
primary =
|
|
484
|
+
# Dummy inferences
|
|
485
|
+
# TODO: pass through the lack of a primary inferences to the app
|
|
486
|
+
primary = EMPTY_INFERENCES
|
|
487
487
|
|
|
488
488
|
if _session is not None and _session.active:
|
|
489
489
|
logger.warning(
|
phoenix/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "3.
|
|
1
|
+
__version__ = "3.22.0"
|
|
File without changes
|
|
File without changes
|