arize-phoenix 2.0.0__py3-none-any.whl → 2.2.0rc0__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-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/METADATA +5 -1
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/RECORD +31 -29
- phoenix/__init__.py +2 -2
- phoenix/core/evals.py +29 -8
- phoenix/core/traces.py +45 -34
- phoenix/experimental/evals/__init__.py +4 -1
- phoenix/experimental/evals/evaluators.py +85 -8
- phoenix/experimental/evals/functions/classify.py +16 -41
- phoenix/experimental/evals/functions/executor.py +1 -0
- phoenix/experimental/evals/models/anthropic.py +171 -0
- phoenix/experimental/evals/models/vertex.py +155 -0
- phoenix/experimental/evals/templates/__init__.py +2 -0
- phoenix/experimental/evals/templates/default_templates.py +12 -0
- phoenix/experimental/evals/utils/__init__.py +64 -2
- phoenix/server/api/schema.py +24 -0
- phoenix/server/app.py +6 -5
- phoenix/server/main.py +6 -7
- phoenix/server/span_handler.py +7 -7
- phoenix/server/static/index.js +586 -499
- phoenix/server/templates/index.html +5 -1
- phoenix/server/trace_handler.py +56 -0
- phoenix/session/session.py +2 -1
- phoenix/trace/exporter.py +4 -3
- phoenix/trace/langchain/tracer.py +14 -4
- phoenix/trace/otel.py +409 -0
- phoenix/trace/semantic_conventions.py +2 -0
- phoenix/trace/v1/__init__.py +0 -4
- phoenix/version.py +1 -0
- phoenix/trace/v1/trace_pb2.py +0 -54
- phoenix/trace/v1/trace_pb2.pyi +0 -361
- phoenix/trace/v1/utils.py +0 -538
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/WHEEL +0 -0
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/licenses/IP_NOTICE +0 -0
- {arize_phoenix-2.0.0.dist-info → arize_phoenix-2.2.0rc0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from io import BytesIO
|
|
3
|
-
from typing import List, Optional, Tuple
|
|
3
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
4
4
|
from urllib.error import HTTPError
|
|
5
5
|
from urllib.request import urlopen
|
|
6
6
|
from zipfile import ZipFile
|
|
@@ -14,10 +14,11 @@ from phoenix.utilities.logging import printif
|
|
|
14
14
|
# This is useful for debugging as well as to just treat the output as a non-parsable category
|
|
15
15
|
NOT_PARSABLE = "NOT_PARSABLE"
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
# values in the default openai function call,
|
|
18
18
|
# defined here only to prevent typos
|
|
19
19
|
_RESPONSE = "response"
|
|
20
20
|
_EXPLANATION = "explanation"
|
|
21
|
+
_FUNCTION_NAME = "record_response"
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
def download_benchmark_dataset(task: str, dataset_name: str) -> pd.DataFrame:
|
|
@@ -108,3 +109,64 @@ def parse_openai_function_call(raw_output: str) -> Tuple[str, Optional[str]]:
|
|
|
108
109
|
unrailed_label = raw_output
|
|
109
110
|
explanation = None
|
|
110
111
|
return unrailed_label, explanation
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def openai_function_call_kwargs(rails: List[str], provide_explanation: bool) -> Dict[str, Any]:
|
|
115
|
+
"""
|
|
116
|
+
Returns keyword arguments needed to invoke an OpenAI model with function
|
|
117
|
+
calling for classification.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
rails (List[str]): The rails to snap the output to.
|
|
121
|
+
|
|
122
|
+
provide_explanation (bool): Whether to provide an explanation.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Dict[str, Any]: A dictionary containing function call arguments.
|
|
126
|
+
"""
|
|
127
|
+
openai_function = _default_openai_function(rails, provide_explanation)
|
|
128
|
+
return {
|
|
129
|
+
"functions": [openai_function],
|
|
130
|
+
"function_call": {"name": openai_function["name"]},
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _default_openai_function(
|
|
135
|
+
rails: List[str],
|
|
136
|
+
with_explanation: bool = False,
|
|
137
|
+
) -> Dict[str, Any]:
|
|
138
|
+
"""
|
|
139
|
+
Returns a default OpenAI function call for classification.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
rails (List[str]): A list of rails to snap the output to.
|
|
143
|
+
|
|
144
|
+
with_explanation (bool, optional): Whether to include an explanation.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Dict[str, Any]: A JSON schema object advertising a function to record
|
|
148
|
+
the result of the LLM's classification.
|
|
149
|
+
"""
|
|
150
|
+
properties = {
|
|
151
|
+
**(
|
|
152
|
+
{
|
|
153
|
+
_EXPLANATION: {
|
|
154
|
+
"type": "string",
|
|
155
|
+
"description": "Explanation of the reasoning for your response.",
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
if with_explanation
|
|
159
|
+
else {}
|
|
160
|
+
),
|
|
161
|
+
_RESPONSE: {"type": "string", "description": "Your response.", "enum": rails},
|
|
162
|
+
}
|
|
163
|
+
required = [*([_EXPLANATION] if with_explanation else []), _RESPONSE]
|
|
164
|
+
return {
|
|
165
|
+
"name": _FUNCTION_NAME,
|
|
166
|
+
"description": "A function to record your response.",
|
|
167
|
+
"parameters": {
|
|
168
|
+
"type": "object",
|
|
169
|
+
"properties": properties,
|
|
170
|
+
"required": required,
|
|
171
|
+
},
|
|
172
|
+
}
|
phoenix/server/api/schema.py
CHANGED
|
@@ -202,6 +202,30 @@ class Query:
|
|
|
202
202
|
clustered_events=clustered_events,
|
|
203
203
|
)
|
|
204
204
|
|
|
205
|
+
@strawberry.field
|
|
206
|
+
def streaming_last_updated_at(
|
|
207
|
+
self,
|
|
208
|
+
info: Info[Context, None],
|
|
209
|
+
) -> Optional[datetime]:
|
|
210
|
+
last_updated_at: Optional[datetime] = None
|
|
211
|
+
if (traces := info.context.traces) is not None and (
|
|
212
|
+
traces_last_updated_at := traces.last_updated_at
|
|
213
|
+
) is not None:
|
|
214
|
+
last_updated_at = (
|
|
215
|
+
traces_last_updated_at
|
|
216
|
+
if last_updated_at is None
|
|
217
|
+
else max(last_updated_at, traces_last_updated_at)
|
|
218
|
+
)
|
|
219
|
+
if (evals := info.context.evals) is not None and (
|
|
220
|
+
evals_last_updated_at := evals.last_updated_at
|
|
221
|
+
) is not None:
|
|
222
|
+
last_updated_at = (
|
|
223
|
+
evals_last_updated_at
|
|
224
|
+
if last_updated_at is None
|
|
225
|
+
else max(last_updated_at, evals_last_updated_at)
|
|
226
|
+
)
|
|
227
|
+
return last_updated_at
|
|
228
|
+
|
|
205
229
|
@strawberry.field
|
|
206
230
|
def spans(
|
|
207
231
|
self,
|
phoenix/server/app.py
CHANGED
|
@@ -28,6 +28,7 @@ from phoenix.server.api.context import Context
|
|
|
28
28
|
from phoenix.server.api.schema import schema
|
|
29
29
|
from phoenix.server.evaluation_handler import EvaluationHandler
|
|
30
30
|
from phoenix.server.span_handler import SpanHandler
|
|
31
|
+
from phoenix.server.trace_handler import TraceHandler
|
|
31
32
|
|
|
32
33
|
logger = logging.getLogger(__name__)
|
|
33
34
|
|
|
@@ -185,11 +186,11 @@ def create_app(
|
|
|
185
186
|
else [
|
|
186
187
|
Route(
|
|
187
188
|
"/v1/spans",
|
|
188
|
-
type(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
),
|
|
189
|
+
type("SpanEndpoint", (SpanHandler,), {"queue": traces}),
|
|
190
|
+
),
|
|
191
|
+
Route(
|
|
192
|
+
"/v1/traces",
|
|
193
|
+
type("TraceEndpoint", (TraceHandler,), {"queue": traces}),
|
|
193
194
|
),
|
|
194
195
|
]
|
|
195
196
|
)
|
phoenix/server/main.py
CHANGED
|
@@ -29,6 +29,7 @@ from phoenix.trace.fixtures import (
|
|
|
29
29
|
_get_trace_fixture_by_name,
|
|
30
30
|
get_evals_from_fixture,
|
|
31
31
|
)
|
|
32
|
+
from phoenix.trace.otel import encode
|
|
32
33
|
from phoenix.trace.span_json_decoder import json_string_to_span
|
|
33
34
|
|
|
34
35
|
logger = logging.getLogger(__name__)
|
|
@@ -148,13 +149,11 @@ if __name__ == "__main__":
|
|
|
148
149
|
traces = Traces()
|
|
149
150
|
evals = Evals()
|
|
150
151
|
if trace_dataset_name is not None:
|
|
151
|
-
fixture_spans =
|
|
152
|
-
json_string_to_span
|
|
153
|
-
_download_traces_fixture(
|
|
154
|
-
_get_trace_fixture_by_name(
|
|
155
|
-
|
|
156
|
-
),
|
|
157
|
-
),
|
|
152
|
+
fixture_spans = (
|
|
153
|
+
encode(json_string_to_span(json_span))
|
|
154
|
+
for json_span in _download_traces_fixture(
|
|
155
|
+
_get_trace_fixture_by_name(trace_dataset_name)
|
|
156
|
+
)
|
|
158
157
|
)
|
|
159
158
|
Thread(
|
|
160
159
|
target=_load_items,
|
phoenix/server/span_handler.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import gzip
|
|
2
2
|
from typing import Protocol
|
|
3
3
|
|
|
4
|
+
import opentelemetry.proto.trace.v1.trace_pb2 as otlp
|
|
4
5
|
from starlette.endpoints import HTTPEndpoint
|
|
5
6
|
from starlette.requests import Request
|
|
6
7
|
from starlette.responses import Response
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
from phoenix.trace.otel import encode
|
|
9
10
|
from phoenix.trace.schemas import Span
|
|
10
11
|
from phoenix.trace.span_json_decoder import json_to_span
|
|
11
|
-
from phoenix.trace.v1.utils import encode
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class SupportsPutSpan(Protocol):
|
|
15
|
-
def put(self, span:
|
|
15
|
+
def put(self, span: otlp.Span) -> None:
|
|
16
16
|
...
|
|
17
17
|
|
|
18
18
|
|
|
@@ -27,13 +27,13 @@ class SpanHandler(HTTPEndpoint):
|
|
|
27
27
|
content_encoding = request.headers.get("content-encoding")
|
|
28
28
|
if content_encoding == "gzip":
|
|
29
29
|
body = gzip.decompress(body)
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
otlp_span = otlp.Span()
|
|
31
|
+
otlp_span.ParseFromString(body)
|
|
32
32
|
else:
|
|
33
33
|
span = json_to_span(await request.json())
|
|
34
34
|
assert isinstance(span, Span)
|
|
35
|
-
|
|
35
|
+
otlp_span = encode(span)
|
|
36
36
|
except Exception:
|
|
37
37
|
return Response(status_code=422)
|
|
38
|
-
self.queue.put(
|
|
38
|
+
self.queue.put(otlp_span)
|
|
39
39
|
return Response()
|