arize-phoenix 5.5.2__py3-none-any.whl → 5.7.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-5.5.2.dist-info → arize_phoenix-5.7.0.dist-info}/METADATA +4 -7
- arize_phoenix-5.7.0.dist-info/RECORD +330 -0
- phoenix/config.py +50 -8
- phoenix/core/model.py +3 -3
- phoenix/core/model_schema.py +41 -50
- phoenix/core/model_schema_adapter.py +17 -16
- phoenix/datetime_utils.py +2 -2
- phoenix/db/bulk_inserter.py +10 -20
- phoenix/db/engines.py +2 -1
- phoenix/db/enums.py +2 -2
- phoenix/db/helpers.py +8 -7
- phoenix/db/insertion/dataset.py +9 -19
- phoenix/db/insertion/document_annotation.py +14 -13
- phoenix/db/insertion/helpers.py +6 -16
- phoenix/db/insertion/span_annotation.py +14 -13
- phoenix/db/insertion/trace_annotation.py +14 -13
- phoenix/db/insertion/types.py +19 -30
- phoenix/db/migrations/versions/3be8647b87d8_add_token_columns_to_spans_table.py +8 -8
- phoenix/db/models.py +28 -28
- phoenix/experiments/evaluators/base.py +2 -1
- phoenix/experiments/evaluators/code_evaluators.py +4 -5
- phoenix/experiments/evaluators/llm_evaluators.py +157 -4
- phoenix/experiments/evaluators/utils.py +3 -2
- phoenix/experiments/functions.py +10 -21
- phoenix/experiments/tracing.py +2 -1
- phoenix/experiments/types.py +20 -29
- phoenix/experiments/utils.py +2 -1
- phoenix/inferences/errors.py +6 -5
- phoenix/inferences/fixtures.py +6 -5
- phoenix/inferences/inferences.py +37 -37
- phoenix/inferences/schema.py +11 -10
- phoenix/inferences/validation.py +13 -14
- phoenix/logging/_formatter.py +3 -3
- phoenix/metrics/__init__.py +5 -4
- phoenix/metrics/binning.py +2 -1
- phoenix/metrics/metrics.py +2 -1
- phoenix/metrics/mixins.py +7 -6
- phoenix/metrics/retrieval_metrics.py +2 -1
- phoenix/metrics/timeseries.py +5 -4
- phoenix/metrics/wrappers.py +2 -2
- phoenix/pointcloud/clustering.py +3 -4
- phoenix/pointcloud/pointcloud.py +7 -5
- phoenix/pointcloud/umap_parameters.py +2 -1
- phoenix/server/api/dataloaders/annotation_summaries.py +12 -19
- phoenix/server/api/dataloaders/average_experiment_run_latency.py +2 -2
- phoenix/server/api/dataloaders/cache/two_tier_cache.py +3 -2
- phoenix/server/api/dataloaders/dataset_example_revisions.py +3 -8
- phoenix/server/api/dataloaders/dataset_example_spans.py +2 -5
- phoenix/server/api/dataloaders/document_evaluation_summaries.py +12 -18
- phoenix/server/api/dataloaders/document_evaluations.py +3 -7
- phoenix/server/api/dataloaders/document_retrieval_metrics.py +6 -13
- phoenix/server/api/dataloaders/experiment_annotation_summaries.py +4 -8
- phoenix/server/api/dataloaders/experiment_error_rates.py +2 -5
- phoenix/server/api/dataloaders/experiment_run_annotations.py +3 -7
- phoenix/server/api/dataloaders/experiment_run_counts.py +1 -5
- phoenix/server/api/dataloaders/experiment_sequence_number.py +2 -5
- phoenix/server/api/dataloaders/latency_ms_quantile.py +21 -30
- phoenix/server/api/dataloaders/min_start_or_max_end_times.py +7 -13
- phoenix/server/api/dataloaders/project_by_name.py +3 -3
- phoenix/server/api/dataloaders/record_counts.py +11 -18
- phoenix/server/api/dataloaders/span_annotations.py +3 -7
- phoenix/server/api/dataloaders/span_dataset_examples.py +3 -8
- phoenix/server/api/dataloaders/span_descendants.py +3 -7
- phoenix/server/api/dataloaders/span_projects.py +2 -2
- phoenix/server/api/dataloaders/token_counts.py +12 -19
- phoenix/server/api/dataloaders/trace_row_ids.py +3 -7
- phoenix/server/api/dataloaders/user_roles.py +3 -3
- phoenix/server/api/dataloaders/users.py +3 -3
- phoenix/server/api/helpers/__init__.py +4 -3
- phoenix/server/api/helpers/dataset_helpers.py +10 -9
- phoenix/server/api/helpers/playground_clients.py +671 -0
- phoenix/server/api/helpers/playground_registry.py +70 -0
- phoenix/server/api/helpers/playground_spans.py +325 -0
- phoenix/server/api/input_types/AddExamplesToDatasetInput.py +2 -2
- phoenix/server/api/input_types/AddSpansToDatasetInput.py +2 -2
- phoenix/server/api/input_types/ChatCompletionInput.py +38 -0
- phoenix/server/api/input_types/ChatCompletionMessageInput.py +13 -1
- phoenix/server/api/input_types/ClusterInput.py +2 -2
- phoenix/server/api/input_types/DeleteAnnotationsInput.py +1 -3
- phoenix/server/api/input_types/DeleteDatasetExamplesInput.py +2 -2
- phoenix/server/api/input_types/DeleteExperimentsInput.py +1 -3
- phoenix/server/api/input_types/DimensionFilter.py +4 -4
- phoenix/server/api/input_types/GenerativeModelInput.py +17 -0
- phoenix/server/api/input_types/Granularity.py +1 -1
- phoenix/server/api/input_types/InvocationParameters.py +156 -13
- phoenix/server/api/input_types/PatchDatasetExamplesInput.py +2 -2
- phoenix/server/api/input_types/TemplateOptions.py +10 -0
- phoenix/server/api/mutations/__init__.py +4 -0
- phoenix/server/api/mutations/chat_mutations.py +374 -0
- phoenix/server/api/mutations/dataset_mutations.py +4 -4
- phoenix/server/api/mutations/experiment_mutations.py +1 -2
- phoenix/server/api/mutations/export_events_mutations.py +7 -7
- phoenix/server/api/mutations/span_annotations_mutations.py +4 -4
- phoenix/server/api/mutations/trace_annotations_mutations.py +4 -4
- phoenix/server/api/mutations/user_mutations.py +4 -4
- phoenix/server/api/openapi/schema.py +2 -2
- phoenix/server/api/queries.py +61 -72
- phoenix/server/api/routers/oauth2.py +4 -4
- phoenix/server/api/routers/v1/datasets.py +22 -36
- phoenix/server/api/routers/v1/evaluations.py +6 -5
- phoenix/server/api/routers/v1/experiment_evaluations.py +2 -2
- phoenix/server/api/routers/v1/experiment_runs.py +2 -2
- phoenix/server/api/routers/v1/experiments.py +4 -4
- phoenix/server/api/routers/v1/spans.py +13 -12
- phoenix/server/api/routers/v1/traces.py +5 -5
- phoenix/server/api/routers/v1/utils.py +5 -5
- phoenix/server/api/schema.py +42 -10
- phoenix/server/api/subscriptions.py +347 -494
- phoenix/server/api/types/AnnotationSummary.py +3 -3
- phoenix/server/api/types/ChatCompletionSubscriptionPayload.py +44 -0
- phoenix/server/api/types/Cluster.py +8 -7
- phoenix/server/api/types/Dataset.py +5 -4
- phoenix/server/api/types/Dimension.py +3 -3
- phoenix/server/api/types/DocumentEvaluationSummary.py +8 -7
- phoenix/server/api/types/EmbeddingDimension.py +6 -5
- phoenix/server/api/types/EvaluationSummary.py +3 -3
- phoenix/server/api/types/Event.py +7 -7
- phoenix/server/api/types/Experiment.py +3 -3
- phoenix/server/api/types/ExperimentComparison.py +2 -4
- phoenix/server/api/types/GenerativeProvider.py +27 -3
- phoenix/server/api/types/Inferences.py +9 -8
- phoenix/server/api/types/InferencesRole.py +2 -2
- phoenix/server/api/types/Model.py +2 -2
- phoenix/server/api/types/Project.py +11 -18
- phoenix/server/api/types/Segments.py +3 -3
- phoenix/server/api/types/Span.py +45 -7
- phoenix/server/api/types/TemplateLanguage.py +9 -0
- phoenix/server/api/types/TimeSeries.py +8 -7
- phoenix/server/api/types/Trace.py +2 -2
- phoenix/server/api/types/UMAPPoints.py +6 -6
- phoenix/server/api/types/User.py +3 -3
- phoenix/server/api/types/node.py +1 -3
- phoenix/server/api/types/pagination.py +4 -4
- phoenix/server/api/utils.py +2 -4
- phoenix/server/app.py +76 -37
- phoenix/server/bearer_auth.py +4 -10
- phoenix/server/dml_event.py +3 -3
- phoenix/server/dml_event_handler.py +10 -24
- phoenix/server/grpc_server.py +3 -2
- phoenix/server/jwt_store.py +22 -21
- phoenix/server/main.py +17 -4
- phoenix/server/oauth2.py +3 -2
- phoenix/server/rate_limiters.py +5 -8
- phoenix/server/static/.vite/manifest.json +31 -31
- phoenix/server/static/assets/components-Csu8UKOs.js +1612 -0
- phoenix/server/static/assets/{index-DCzakdJq.js → index-Bk5C9EA7.js} +2 -2
- phoenix/server/static/assets/{pages-CAL1FDMt.js → pages-UeWaKXNs.js} +337 -442
- phoenix/server/static/assets/{vendor-6IcPAw_j.js → vendor-CtqfhlbC.js} +6 -6
- phoenix/server/static/assets/{vendor-arizeai-DRZuoyuF.js → vendor-arizeai-C_3SBz56.js} +2 -2
- phoenix/server/static/assets/{vendor-codemirror-DVE2_WBr.js → vendor-codemirror-wfdk9cjp.js} +1 -1
- phoenix/server/static/assets/{vendor-recharts-DwrexFA4.js → vendor-recharts-BiVnSv90.js} +1 -1
- phoenix/server/templates/index.html +1 -0
- phoenix/server/thread_server.py +1 -1
- phoenix/server/types.py +17 -29
- phoenix/services.py +8 -3
- phoenix/session/client.py +12 -24
- phoenix/session/data_extractor.py +3 -3
- phoenix/session/evaluation.py +1 -2
- phoenix/session/session.py +26 -21
- phoenix/trace/attributes.py +16 -28
- phoenix/trace/dsl/filter.py +17 -21
- phoenix/trace/dsl/helpers.py +3 -3
- phoenix/trace/dsl/query.py +13 -22
- phoenix/trace/fixtures.py +11 -17
- phoenix/trace/otel.py +5 -15
- phoenix/trace/projects.py +3 -2
- phoenix/trace/schemas.py +2 -2
- phoenix/trace/span_evaluations.py +9 -8
- phoenix/trace/span_json_decoder.py +3 -3
- phoenix/trace/span_json_encoder.py +2 -2
- phoenix/trace/trace_dataset.py +6 -5
- phoenix/trace/utils.py +6 -6
- phoenix/utilities/deprecation.py +3 -2
- phoenix/utilities/error_handling.py +3 -2
- phoenix/utilities/json.py +2 -1
- phoenix/utilities/logging.py +2 -2
- phoenix/utilities/project.py +1 -1
- phoenix/utilities/re.py +3 -4
- phoenix/utilities/template_formatters.py +16 -5
- phoenix/version.py +1 -1
- arize_phoenix-5.5.2.dist-info/RECORD +0 -321
- phoenix/server/static/assets/components-hX0LgYz3.js +0 -1428
- {arize_phoenix-5.5.2.dist-info → arize_phoenix-5.7.0.dist-info}/WHEEL +0 -0
- {arize_phoenix-5.5.2.dist-info → arize_phoenix-5.7.0.dist-info}/entry_points.txt +0 -0
- {arize_phoenix-5.5.2.dist-info → arize_phoenix-5.7.0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-5.5.2.dist-info → arize_phoenix-5.7.0.dist-info}/licenses/LICENSE +0 -0
phoenix/trace/fixtures.py
CHANGED
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
import shutil
|
|
3
3
|
from binascii import hexlify
|
|
4
4
|
from collections import defaultdict
|
|
5
|
+
from collections.abc import Iterable, Iterator, Sequence
|
|
5
6
|
from dataclasses import dataclass, field, replace
|
|
6
7
|
from datetime import datetime, timezone
|
|
7
8
|
from io import StringIO
|
|
@@ -9,15 +10,8 @@ from random import getrandbits
|
|
|
9
10
|
from tempfile import NamedTemporaryFile
|
|
10
11
|
from time import sleep, time
|
|
11
12
|
from typing import (
|
|
12
|
-
DefaultDict,
|
|
13
|
-
Dict,
|
|
14
|
-
Iterable,
|
|
15
|
-
Iterator,
|
|
16
|
-
List,
|
|
17
13
|
NamedTuple,
|
|
18
14
|
Optional,
|
|
19
|
-
Sequence,
|
|
20
|
-
Tuple,
|
|
21
15
|
cast,
|
|
22
16
|
)
|
|
23
17
|
from urllib.parse import urljoin
|
|
@@ -280,7 +274,7 @@ random_fixture = TracesFixture(
|
|
|
280
274
|
file_name="random.jsonl",
|
|
281
275
|
)
|
|
282
276
|
|
|
283
|
-
TRACES_FIXTURES:
|
|
277
|
+
TRACES_FIXTURES: list[TracesFixture] = [
|
|
284
278
|
demo_llama_index_rag_fixture,
|
|
285
279
|
demo_llama_index_rag_llm_fixture,
|
|
286
280
|
demo_langgraph_agent_fixture,
|
|
@@ -298,10 +292,10 @@ TRACES_FIXTURES: List[TracesFixture] = [
|
|
|
298
292
|
anthropic_tools_fixture,
|
|
299
293
|
]
|
|
300
294
|
|
|
301
|
-
NAME_TO_TRACES_FIXTURE:
|
|
295
|
+
NAME_TO_TRACES_FIXTURE: dict[str, TracesFixture] = {
|
|
302
296
|
fixture.name: fixture for fixture in TRACES_FIXTURES
|
|
303
297
|
}
|
|
304
|
-
PROJ_NAME_TO_TRACES_FIXTURE:
|
|
298
|
+
PROJ_NAME_TO_TRACES_FIXTURE: defaultdict[str, list[TracesFixture]] = defaultdict(list)
|
|
305
299
|
for fixture in TRACES_FIXTURES:
|
|
306
300
|
if fixture.project_name:
|
|
307
301
|
PROJ_NAME_TO_TRACES_FIXTURE[fixture.project_name].append(fixture)
|
|
@@ -322,7 +316,7 @@ def get_trace_fixture_by_name(fixture_name: str) -> TracesFixture:
|
|
|
322
316
|
return NAME_TO_TRACES_FIXTURE[fixture_name]
|
|
323
317
|
|
|
324
318
|
|
|
325
|
-
def get_trace_fixtures_by_project_name(proj_name: str) ->
|
|
319
|
+
def get_trace_fixtures_by_project_name(proj_name: str) -> list[TracesFixture]:
|
|
326
320
|
"""
|
|
327
321
|
Returns a dictionary of project name (key) and set of TracesFixtures (value)
|
|
328
322
|
whose project name matches the input name.
|
|
@@ -437,7 +431,7 @@ def _read_eval_fixture(eval_fixture: EvaluationFixture) -> Iterator[pb.Evaluatio
|
|
|
437
431
|
explanation=StringValue(value=cast(str, explanation)) if explanation else None,
|
|
438
432
|
)
|
|
439
433
|
if isinstance(eval_fixture, DocumentEvaluationFixture):
|
|
440
|
-
span_id, document_position = cast(
|
|
434
|
+
span_id, document_position = cast(tuple[str, int], index)
|
|
441
435
|
# Legacy fixture files contain UUID strings for span_ids. The hyphens in these
|
|
442
436
|
# strings need to be removed because we are also removing the hyphens from the
|
|
443
437
|
# span_ids of their corresponding traces. In general, hyphen is not an allowed
|
|
@@ -476,10 +470,10 @@ def _url(
|
|
|
476
470
|
def reset_fixture_span_ids_and_timestamps(
|
|
477
471
|
spans: Iterable[Span],
|
|
478
472
|
evals: Iterable[pb.Evaluation] = (),
|
|
479
|
-
) ->
|
|
473
|
+
) -> tuple[list[Span], list[pb.Evaluation]]:
|
|
480
474
|
old_spans, old_evals = list(spans), list(evals)
|
|
481
|
-
new_trace_ids:
|
|
482
|
-
new_span_ids:
|
|
475
|
+
new_trace_ids: dict[str, str] = {}
|
|
476
|
+
new_span_ids: dict[str, str] = {}
|
|
483
477
|
for old_span in old_spans:
|
|
484
478
|
new_trace_ids[old_span.context.trace_id] = _new_trace_id()
|
|
485
479
|
new_span_ids[old_span.context.span_id] = _new_span_id()
|
|
@@ -495,8 +489,8 @@ def reset_fixture_span_ids_and_timestamps(
|
|
|
495
489
|
new_span_ids[span_id] = _new_span_id()
|
|
496
490
|
max_end_time = max(old_span.end_time for old_span in old_spans)
|
|
497
491
|
time_diff = datetime.now(timezone.utc) - max_end_time
|
|
498
|
-
new_spans:
|
|
499
|
-
new_evals:
|
|
492
|
+
new_spans: list[Span] = []
|
|
493
|
+
new_evals: list[pb.Evaluation] = []
|
|
500
494
|
for old_span in old_spans:
|
|
501
495
|
new_trace_id = new_trace_ids[old_span.context.trace_id]
|
|
502
496
|
new_span_id = new_span_ids[old_span.context.span_id]
|
phoenix/trace/otel.py
CHANGED
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from binascii import hexlify, unhexlify
|
|
3
|
+
from collections.abc import Iterable, Iterator, Mapping, Sequence
|
|
3
4
|
from datetime import datetime, timezone
|
|
4
5
|
from types import MappingProxyType
|
|
5
|
-
from typing import
|
|
6
|
-
Any,
|
|
7
|
-
Dict,
|
|
8
|
-
Iterable,
|
|
9
|
-
Iterator,
|
|
10
|
-
Mapping,
|
|
11
|
-
Optional,
|
|
12
|
-
Sequence,
|
|
13
|
-
SupportsFloat,
|
|
14
|
-
Tuple,
|
|
15
|
-
cast,
|
|
16
|
-
)
|
|
6
|
+
from typing import Any, Optional, SupportsFloat, cast
|
|
17
7
|
|
|
18
8
|
import numpy as np
|
|
19
9
|
import opentelemetry.proto.trace.v1.trace_pb2 as otlp
|
|
@@ -133,7 +123,7 @@ def _decode_unix_nano(time_unix_nano: int) -> datetime:
|
|
|
133
123
|
|
|
134
124
|
def _decode_key_values(
|
|
135
125
|
key_values: Iterable[KeyValue],
|
|
136
|
-
) -> Iterator[
|
|
126
|
+
) -> Iterator[tuple[str, Any]]:
|
|
137
127
|
return ((kv.key, _decode_value(kv.value)) for kv in key_values)
|
|
138
128
|
|
|
139
129
|
|
|
@@ -169,7 +159,7 @@ _STATUS_DECODING = MappingProxyType(
|
|
|
169
159
|
)
|
|
170
160
|
|
|
171
161
|
|
|
172
|
-
def _decode_status(otlp_status: otlp.Status) ->
|
|
162
|
+
def _decode_status(otlp_status: otlp.Status) -> tuple[SpanStatusCode, StatusMessage]:
|
|
173
163
|
status_code = _STATUS_DECODING.get(otlp_status.code, SpanStatusCode.UNSET)
|
|
174
164
|
return status_code, otlp_status.message
|
|
175
165
|
|
|
@@ -186,7 +176,7 @@ def encode_span_to_otlp(span: Span) -> otlp.Span:
|
|
|
186
176
|
start_time_unix_nano: int = int(span.start_time.timestamp() * _BILLION)
|
|
187
177
|
end_time_unix_nano: int = int(span.end_time.timestamp() * _BILLION) if span.end_time else 0
|
|
188
178
|
|
|
189
|
-
attributes:
|
|
179
|
+
attributes: dict[str, Any] = dict(span.attributes)
|
|
190
180
|
|
|
191
181
|
for key, value in span.attributes.items():
|
|
192
182
|
if value is None:
|
phoenix/trace/projects.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import types
|
|
2
|
-
from
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import Any, Optional
|
|
3
4
|
|
|
4
5
|
from openinference.semconv.resource import ResourceAttributes
|
|
5
6
|
from opentelemetry.sdk import trace
|
|
@@ -58,7 +59,7 @@ class using_project:
|
|
|
58
59
|
|
|
59
60
|
def __exit__(
|
|
60
61
|
self,
|
|
61
|
-
exc_type: Optional[
|
|
62
|
+
exc_type: Optional[type[BaseException]],
|
|
62
63
|
exc_value: Optional[BaseException],
|
|
63
64
|
traceback: Optional[types.TracebackType],
|
|
64
65
|
) -> None:
|
phoenix/trace/schemas.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Mapping, NamedTuple, Optional
|
|
5
5
|
from uuid import UUID
|
|
6
6
|
|
|
7
7
|
EXCEPTION_TYPE = "exception.type"
|
|
@@ -169,7 +169,7 @@ class Span:
|
|
|
169
169
|
OpenTelemetry Inspiration:
|
|
170
170
|
https://opentelemetry.io/docs/concepts/signals/traces/#span-events
|
|
171
171
|
"""
|
|
172
|
-
events:
|
|
172
|
+
events: list[SpanEvent]
|
|
173
173
|
|
|
174
174
|
"""
|
|
175
175
|
An extension of the OpenTelemetry Span interface to include the
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from abc import ABC
|
|
3
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
3
4
|
from dataclasses import dataclass, field
|
|
4
5
|
from itertools import product
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from types import MappingProxyType
|
|
7
|
-
from typing import Any,
|
|
8
|
+
from typing import Any, Optional, Union
|
|
8
9
|
from uuid import UUID, uuid4
|
|
9
10
|
|
|
10
11
|
import pandas as pd
|
|
@@ -20,11 +21,11 @@ EVAL_PARQUET_FILE_NAME = "evaluations-{id}.parquet"
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class NeedsNamedIndex(ABC):
|
|
23
|
-
index_names: Mapping[
|
|
24
|
-
all_valid_index_name_sorted_combos:
|
|
24
|
+
index_names: Mapping[tuple[str, ...], Callable[[Any], bool]]
|
|
25
|
+
all_valid_index_name_sorted_combos: set[tuple[str, ...]]
|
|
25
26
|
|
|
26
27
|
@classmethod
|
|
27
|
-
def preferred_names(cls) ->
|
|
28
|
+
def preferred_names(cls) -> list[str]:
|
|
28
29
|
return [choices[0] for choices in cls.index_names.keys()]
|
|
29
30
|
|
|
30
31
|
@classmethod
|
|
@@ -43,7 +44,7 @@ class NeedsNamedIndex(ABC):
|
|
|
43
44
|
)
|
|
44
45
|
|
|
45
46
|
@classmethod
|
|
46
|
-
def find_valid_index_names(cls, dtypes: "pd.Series[Any]") -> Optional[
|
|
47
|
+
def find_valid_index_names(cls, dtypes: "pd.Series[Any]") -> Optional[list[str]]:
|
|
47
48
|
valid_names = []
|
|
48
49
|
for names, check_type in cls.index_names.items():
|
|
49
50
|
for name in names:
|
|
@@ -92,7 +93,7 @@ class Evaluations(NeedsNamedIndex, NeedsResultColumns, ABC):
|
|
|
92
93
|
f"dataframe=<rows: {len(self.dataframe)!r}>)"
|
|
93
94
|
)
|
|
94
95
|
|
|
95
|
-
def __dir__(self) ->
|
|
96
|
+
def __dir__(self) -> list[str]:
|
|
96
97
|
return ["get_dataframe"]
|
|
97
98
|
|
|
98
99
|
def get_dataframe(self, prefix_columns_with_name: bool = True) -> pd.DataFrame:
|
|
@@ -153,7 +154,7 @@ class Evaluations(NeedsNamedIndex, NeedsResultColumns, ABC):
|
|
|
153
154
|
|
|
154
155
|
def __init_subclass__(
|
|
155
156
|
cls,
|
|
156
|
-
index_names: Mapping[
|
|
157
|
+
index_names: Mapping[tuple[str, ...], Callable[[Any], bool]],
|
|
157
158
|
**kwargs: Any,
|
|
158
159
|
) -> None:
|
|
159
160
|
super().__init_subclass__(**kwargs)
|
|
@@ -327,7 +328,7 @@ class TraceEvaluations(
|
|
|
327
328
|
): ...
|
|
328
329
|
|
|
329
330
|
|
|
330
|
-
def _parse_schema_metadata(schema: Schema) ->
|
|
331
|
+
def _parse_schema_metadata(schema: Schema) -> tuple[UUID, str, type[Evaluations]]:
|
|
331
332
|
"""
|
|
332
333
|
Validates and parses the pyarrow schema metadata.
|
|
333
334
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from datetime import datetime
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, Optional
|
|
4
4
|
|
|
5
5
|
from openinference.semconv.trace import SpanAttributes
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ INPUT_MIME_TYPE = SpanAttributes.INPUT_MIME_TYPE
|
|
|
22
22
|
OUTPUT_MIME_TYPE = SpanAttributes.OUTPUT_MIME_TYPE
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
def json_to_attributes(obj: Optional[
|
|
25
|
+
def json_to_attributes(obj: Optional[dict[str, Any]]) -> dict[str, Any]:
|
|
26
26
|
if obj is None:
|
|
27
27
|
return {}
|
|
28
28
|
if not isinstance(obj, dict):
|
|
@@ -34,7 +34,7 @@ def json_to_attributes(obj: Optional[Dict[str, Any]]) -> Dict[str, Any]:
|
|
|
34
34
|
return obj
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
def json_to_span(data:
|
|
37
|
+
def json_to_span(data: dict[str, Any]) -> Any:
|
|
38
38
|
"""
|
|
39
39
|
A hook for json.loads to convert a dict to a Span object.
|
|
40
40
|
"""
|
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
from dataclasses import asdict
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from enum import Enum
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
@@ -60,5 +60,5 @@ def span_to_json(span: Span) -> str:
|
|
|
60
60
|
return json.dumps(span, cls=SpanJSONEncoder)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
def spans_to_jsonl(spans:
|
|
63
|
+
def spans_to_jsonl(spans: list[Span]) -> str:
|
|
64
64
|
return "\n".join(span_to_json(span) for span in spans)
|
phoenix/trace/trace_dataset.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from collections.abc import Iterable, Iterator
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
from pathlib import Path
|
|
4
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Optional, Union, cast
|
|
5
6
|
from uuid import UUID, uuid4
|
|
6
7
|
from warnings import warn
|
|
7
8
|
|
|
@@ -116,7 +117,7 @@ class TraceDataset:
|
|
|
116
117
|
A human readable name for the dataset.
|
|
117
118
|
"""
|
|
118
119
|
dataframe: pd.DataFrame
|
|
119
|
-
evaluations:
|
|
120
|
+
evaluations: list[Evaluations] = []
|
|
120
121
|
_id: UUID
|
|
121
122
|
_data_file_name: str = "data.parquet"
|
|
122
123
|
|
|
@@ -152,11 +153,11 @@ class TraceDataset:
|
|
|
152
153
|
self.evaluations = list(evaluations)
|
|
153
154
|
|
|
154
155
|
@classmethod
|
|
155
|
-
def from_spans(cls, spans:
|
|
156
|
+
def from_spans(cls, spans: list[Span]) -> "TraceDataset":
|
|
156
157
|
"""Creates a TraceDataset from a list of spans.
|
|
157
158
|
|
|
158
159
|
Args:
|
|
159
|
-
spans (
|
|
160
|
+
spans (list[Span]): A list of spans.
|
|
160
161
|
|
|
161
162
|
Returns:
|
|
162
163
|
TraceDataset: A TraceDataset containing the spans.
|
|
@@ -349,7 +350,7 @@ class TraceDataset:
|
|
|
349
350
|
return pd.concat([df, evals_df], axis=1)
|
|
350
351
|
|
|
351
352
|
|
|
352
|
-
def _parse_schema_metadata(schema: Schema) ->
|
|
353
|
+
def _parse_schema_metadata(schema: Schema) -> tuple[UUID, str, list[UUID]]:
|
|
353
354
|
"""
|
|
354
355
|
Returns parsed metadata from a parquet schema or raises an exception if the
|
|
355
356
|
metadata is invalid.
|
phoenix/trace/utils.py
CHANGED
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
import os
|
|
3
3
|
import re
|
|
4
4
|
from traceback import format_exception
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Optional, cast
|
|
6
6
|
from urllib import request
|
|
7
7
|
|
|
8
8
|
import pandas as pd
|
|
@@ -14,16 +14,16 @@ def parse_file_extension(file_path: str) -> str:
|
|
|
14
14
|
|
|
15
15
|
def download_json_traces_fixture(
|
|
16
16
|
url: str,
|
|
17
|
-
) ->
|
|
17
|
+
) -> list[str]:
|
|
18
18
|
"""
|
|
19
19
|
Stores the traces fixture as list of jsons from the jsonl files in the phoenix bucket.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
with request.urlopen(url) as f:
|
|
23
|
-
return cast(
|
|
23
|
+
return cast(list[str], f.readlines())
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def json_lines_to_df(lines:
|
|
26
|
+
def json_lines_to_df(lines: list[str]) -> pd.DataFrame:
|
|
27
27
|
"""
|
|
28
28
|
Convert a list of JSON line strings to a Pandas DataFrame.
|
|
29
29
|
"""
|
|
@@ -56,9 +56,9 @@ def get_stacktrace(exception: BaseException) -> str:
|
|
|
56
56
|
_VERSION_TRIPLET_REGEX = re.compile(r"(\d+)\.(\d+)\.(\d+)")
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def extract_version_triplet(version: str) -> Optional[
|
|
59
|
+
def extract_version_triplet(version: str) -> Optional[tuple[int, int, int]]:
|
|
60
60
|
return (
|
|
61
|
-
cast(
|
|
61
|
+
cast(tuple[int, int, int], tuple(map(int, match.groups())))
|
|
62
62
|
if (match := _VERSION_TRIPLET_REGEX.search(version))
|
|
63
63
|
else None
|
|
64
64
|
)
|
phoenix/utilities/deprecation.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import warnings
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from typing import Any, TypeVar
|
|
4
5
|
|
|
5
|
-
GenericClass = TypeVar("GenericClass", bound=
|
|
6
|
+
GenericClass = TypeVar("GenericClass", bound=type[Any])
|
|
6
7
|
CallableType = TypeVar("CallableType", bound=Callable[..., Any])
|
|
7
8
|
|
|
8
9
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import traceback
|
|
3
|
-
from
|
|
3
|
+
from collections.abc import Callable, Iterable
|
|
4
|
+
from typing import Any, Optional, TypeVar, cast
|
|
4
5
|
|
|
5
6
|
F = TypeVar("F", bound=Callable[..., Any])
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def graceful_fallback(
|
|
9
|
-
fallback_method: Callable[..., Any], exceptions: Optional[Iterable[
|
|
10
|
+
fallback_method: Callable[..., Any], exceptions: Optional[Iterable[type[BaseException]]] = None
|
|
10
11
|
) -> Callable[[F], F]:
|
|
11
12
|
"""
|
|
12
13
|
Decorator that reroutes failing functions to a specified fallback method.
|
phoenix/utilities/json.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import dataclasses
|
|
2
2
|
import datetime
|
|
3
|
+
from collections.abc import Mapping, Sequence
|
|
3
4
|
from enum import Enum
|
|
4
5
|
from pathlib import Path
|
|
5
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, Union, get_args, get_origin
|
|
6
7
|
|
|
7
8
|
import numpy as np
|
|
8
9
|
from strawberry import UNSET
|
phoenix/utilities/logging.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# A collection of printing and logging utilities
|
|
2
2
|
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any
|
|
4
4
|
|
|
5
5
|
from tqdm.auto import tqdm
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ def printif(condition: bool, *args: Any, **kwargs: Any) -> None:
|
|
|
10
10
|
tqdm.write(*args, **kwargs)
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def log_a_list(list_of_str:
|
|
13
|
+
def log_a_list(list_of_str: list[str], join_word: str) -> str:
|
|
14
14
|
if list_of_str is None or len(list_of_str) == 0:
|
|
15
15
|
return ""
|
|
16
16
|
if len(list_of_str) == 1:
|
phoenix/utilities/project.py
CHANGED
phoenix/utilities/re.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from re import compile, split
|
|
3
|
-
from typing import Dict, List
|
|
4
3
|
from urllib.parse import unquote
|
|
5
4
|
|
|
6
5
|
logger = logging.getLogger(__name__)
|
|
@@ -19,7 +18,7 @@ _HEADER_PATTERN = compile(_KEY_VALUE_FORMAT)
|
|
|
19
18
|
_DELIMITER_PATTERN = compile(r"[ \t]*,[ \t]*")
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
def parse_env_headers(s: str) ->
|
|
21
|
+
def parse_env_headers(s: str) -> dict[str, str]:
|
|
23
22
|
"""
|
|
24
23
|
Parse ``s``, which is a ``str`` instance containing HTTP headers encoded
|
|
25
24
|
for use in ENV variables per the W3C Baggage HTTP header format at
|
|
@@ -28,8 +27,8 @@ def parse_env_headers(s: str) -> Dict[str, str]:
|
|
|
28
27
|
|
|
29
28
|
src: https://github.com/open-telemetry/opentelemetry-python/blob/2d5cd58f33bd8a16f45f30be620a96699bc14297/opentelemetry-api/src/opentelemetry/util/re.py#L52
|
|
30
29
|
"""
|
|
31
|
-
headers:
|
|
32
|
-
headers_list:
|
|
30
|
+
headers: dict[str, str] = {}
|
|
31
|
+
headers_list: list[str] = split(_DELIMITER_PATTERN, s)
|
|
33
32
|
for header in headers_list:
|
|
34
33
|
if not header: # empty string
|
|
35
34
|
continue
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
+
from collections.abc import Iterable
|
|
3
4
|
from string import Formatter
|
|
4
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class TemplateFormatter(ABC):
|
|
8
9
|
@abstractmethod
|
|
9
|
-
def parse(self, template: str) ->
|
|
10
|
+
def parse(self, template: str) -> set[str]:
|
|
10
11
|
"""
|
|
11
12
|
Parse the template and return a set of variable names.
|
|
12
13
|
"""
|
|
@@ -18,7 +19,9 @@ class TemplateFormatter(ABC):
|
|
|
18
19
|
"""
|
|
19
20
|
template_variable_names = self.parse(template)
|
|
20
21
|
if missing_template_variables := template_variable_names - set(variables.keys()):
|
|
21
|
-
raise
|
|
22
|
+
raise TemplateFormatterError(
|
|
23
|
+
f"Missing template variable(s): {', '.join(missing_template_variables)}"
|
|
24
|
+
)
|
|
22
25
|
return self._format(template, template_variable_names, **variables)
|
|
23
26
|
|
|
24
27
|
@abstractmethod
|
|
@@ -37,7 +40,7 @@ class FStringTemplateFormatter(TemplateFormatter):
|
|
|
37
40
|
'world'
|
|
38
41
|
"""
|
|
39
42
|
|
|
40
|
-
def parse(self, template: str) ->
|
|
43
|
+
def parse(self, template: str) -> set[str]:
|
|
41
44
|
return set(field_name for _, field_name, _, _ in Formatter().parse(template) if field_name)
|
|
42
45
|
|
|
43
46
|
def _format(self, template: str, variable_names: Iterable[str], **variables: Any) -> str:
|
|
@@ -57,7 +60,7 @@ class MustacheTemplateFormatter(TemplateFormatter):
|
|
|
57
60
|
|
|
58
61
|
PATTERN = re.compile(r"(?<!\\){{\s*(\w+)\s*}}")
|
|
59
62
|
|
|
60
|
-
def parse(self, template: str) ->
|
|
63
|
+
def parse(self, template: str) -> set[str]:
|
|
61
64
|
return set(match for match in re.findall(self.PATTERN, template))
|
|
62
65
|
|
|
63
66
|
def _format(self, template: str, variable_names: Iterable[str], **variables: Any) -> str:
|
|
@@ -68,3 +71,11 @@ class MustacheTemplateFormatter(TemplateFormatter):
|
|
|
68
71
|
string=template,
|
|
69
72
|
)
|
|
70
73
|
return template
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class TemplateFormatterError(Exception):
|
|
77
|
+
"""
|
|
78
|
+
An error raised when template formatting fails.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
pass
|
phoenix/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "5.
|
|
1
|
+
__version__ = "5.7.0"
|