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

phoenix/session/client.py CHANGED
@@ -44,7 +44,7 @@ from phoenix.config import (
44
44
  )
45
45
  from phoenix.datetime_utils import normalize_datetime
46
46
  from phoenix.db.insertion.dataset import DatasetKeys
47
- from phoenix.experiments.types import Dataset, Example
47
+ from phoenix.experiments.types import Dataset, Example, Experiment
48
48
  from phoenix.session.data_extractor import DEFAULT_SPAN_LIMIT, TraceDataExtractor
49
49
  from phoenix.trace import Evaluations, TraceDataset
50
50
  from phoenix.trace.dsl import SpanQuery
@@ -571,6 +571,22 @@ class Client(TraceDataExtractor):
571
571
  action="append",
572
572
  )
573
573
 
574
+ def get_experiment(self, *, experiment_id: str) -> Experiment:
575
+ """
576
+ Get an experiment by ID.
577
+
578
+ Retrieve an Experiment object by ID, enables running `evaluate_experiment` after finishing
579
+ the initial experiment run.
580
+
581
+ Args:
582
+ experiment_id (str): ID of the experiment. This can be found in the UI.
583
+ """
584
+ response = self._client.get(
585
+ url=urljoin(self._base_url, f"v1/experiments/{experiment_id}"),
586
+ )
587
+ experiment = response.json()["data"]
588
+ return Experiment.from_dict(experiment)
589
+
574
590
  def _upload_tabular_dataset(
575
591
  self,
576
592
  table: Union[str, Path, pd.DataFrame],
@@ -112,7 +112,9 @@ def get_qa_with_reference(
112
112
  # Consolidate duplicate rows via concatenation. This can happen if there are multiple
113
113
  # retriever spans in the same trace. We simply concatenate all of them (in no particular
114
114
  # order) into a single row.
115
- ref = df_docs.groupby("context.trace_id")["reference"].apply(lambda x: separator.join(x))
115
+ ref = df_docs.groupby("context.trace_id")["reference"].apply(
116
+ lambda x: separator.join(x.dropna())
117
+ )
116
118
  df_ref = pd.DataFrame({"reference": ref})
117
119
  df_qa_ref = pd.concat([df_qa, df_ref], axis=1, join="inner").set_index("context.span_id")
118
120
  return df_qa_ref
phoenix/trace/fixtures.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  import shutil
3
3
  from binascii import hexlify
4
+ from collections import defaultdict
4
5
  from dataclasses import dataclass, field, replace
5
6
  from datetime import datetime, timezone
6
7
  from io import StringIO
@@ -22,6 +23,7 @@ from phoenix.trace.trace_dataset import TraceDataset
22
23
  from phoenix.trace.utils import download_json_traces_fixture, is_jsonl_file, json_lines_to_df
23
24
 
24
25
  logger = logging.getLogger(__name__)
26
+ logger.setLevel(logging.INFO)
25
27
  logger.addHandler(logging.NullHandler())
26
28
 
27
29
 
@@ -81,10 +83,12 @@ class TracesFixture:
81
83
  file_name: str
82
84
  evaluation_fixtures: Iterable[EvaluationFixture] = ()
83
85
  dataset_fixtures: Iterable[DatasetFixture] = ()
86
+ project_name: Optional[str] = None
84
87
 
85
88
 
86
89
  demo_llama_index_rag_fixture = TracesFixture(
87
90
  name="demo_llama_index_rag",
91
+ project_name="demo_llama_index",
88
92
  description="Traces and evaluations of a RAG chatbot using LlamaIndex.",
89
93
  file_name="demo_llama_index_rag_traces.parquet",
90
94
  evaluation_fixtures=(
@@ -105,6 +109,7 @@ demo_llama_index_rag_fixture = TracesFixture(
105
109
 
106
110
  demo_llama_index_rag_llm_fixture = TracesFixture(
107
111
  name="demo_llama_index_rag_llm",
112
+ project_name="demo_llama_index_rag_llm",
108
113
  description="LLM traces for RAG chatbot using LlamaIndex.",
109
114
  file_name="demo_llama_index_llm_all_spans.parquet",
110
115
  )
@@ -173,6 +178,7 @@ llama_index_rag_fixture_with_davinci = TracesFixture(
173
178
 
174
179
  langchain_rag_stuff_document_chain_fixture = TracesFixture(
175
180
  name="langchain_rag_stuff_document_chain",
181
+ project_name="demo_langchain_rag",
176
182
  description="LangChain RAG data",
177
183
  file_name="langchain_rag.parquet",
178
184
  )
@@ -191,12 +197,14 @@ langchain_qa_with_sources_fixture = TracesFixture(
191
197
 
192
198
  vision_fixture = TracesFixture(
193
199
  name="vision",
200
+ project_name="demo_multimodal",
194
201
  description="Vision LLM Requests",
195
202
  file_name="vision_fixture_trace_datasets.parquet",
196
203
  )
197
204
 
198
205
  random_fixture = TracesFixture(
199
206
  name="random",
207
+ project_name="demo_random",
200
208
  description="Randomly generated traces",
201
209
  file_name="random.jsonl",
202
210
  )
@@ -214,12 +222,18 @@ TRACES_FIXTURES: List[TracesFixture] = [
214
222
  vision_fixture,
215
223
  ]
216
224
 
217
- NAME_TO_TRACES_FIXTURE = {fixture.name: fixture for fixture in TRACES_FIXTURES}
225
+ NAME_TO_TRACES_FIXTURE: Dict[str, TracesFixture] = {
226
+ fixture.name: fixture for fixture in TRACES_FIXTURES
227
+ }
228
+ PROJ_NAME_TO_TRACES_FIXTURE = defaultdict(list)
229
+ for fixture in TRACES_FIXTURES:
230
+ if fixture.project_name:
231
+ PROJ_NAME_TO_TRACES_FIXTURE[fixture.project_name].append(fixture)
218
232
 
219
233
 
220
234
  def get_trace_fixture_by_name(fixture_name: str) -> TracesFixture:
221
235
  """
222
- Returns the fixture whose name matches the input name.
236
+ Returns the trace fixture whose name matches the input name.
223
237
 
224
238
  Raises
225
239
  ------
@@ -232,6 +246,24 @@ def get_trace_fixture_by_name(fixture_name: str) -> TracesFixture:
232
246
  return NAME_TO_TRACES_FIXTURE[fixture_name]
233
247
 
234
248
 
249
+ def get_trace_fixtures_by_project_name(proj_name: str) -> List[TracesFixture]:
250
+ """
251
+ Returns a dictionary of project name (key) and set of TracesFixtures (value)
252
+ whose project name matches the input name.
253
+
254
+ Raises
255
+ ------
256
+ ValueError
257
+ if the input fixture name does not match any known project names.
258
+ """
259
+ if proj_name not in PROJ_NAME_TO_TRACES_FIXTURE:
260
+ valid_fixture_proj_names = ", ".join(PROJ_NAME_TO_TRACES_FIXTURE.keys())
261
+ raise ValueError(
262
+ f'"{proj_name}" is invalid. Valid project names are: {valid_fixture_proj_names}'
263
+ )
264
+ return PROJ_NAME_TO_TRACES_FIXTURE[proj_name]
265
+
266
+
235
267
  def load_example_traces(fixture_name: str) -> TraceDataset:
236
268
  """
237
269
  Loads a trace dataframe by name.
@@ -246,7 +278,16 @@ def load_example_traces(fixture_name: str) -> TraceDataset:
246
278
  if is_jsonl_file(fixture.file_name):
247
279
  return TraceDataset(json_lines_to_df(download_json_traces_fixture(url)))
248
280
 
249
- return TraceDataset(pd.read_parquet(url))
281
+ try:
282
+ df = pd.read_parquet(url)
283
+ except Exception as e:
284
+ logger.warning(
285
+ f"Failed to download example traces from {url=} due to exception {e=}. "
286
+ "Returning empty TraceDataset"
287
+ )
288
+ df = pd.DataFrame()
289
+
290
+ return TraceDataset(df)
250
291
 
251
292
 
252
293
  def get_dataset_fixtures(fixture_name: str) -> Iterable[DatasetFixture]:
@@ -305,7 +346,9 @@ def send_dataset_fixtures(
305
346
  def get_evals_from_fixture(fixture_name: str) -> Iterator[pb.Evaluation]:
306
347
  fixture = get_trace_fixture_by_name(fixture_name)
307
348
  for eval_fixture in fixture.evaluation_fixtures:
308
- print(eval_fixture)
349
+ logger.info(
350
+ f"Loading eval fixture '{eval_fixture.evaluation_name}' from '{eval_fixture.file_name}'"
351
+ )
309
352
  yield from _read_eval_fixture(eval_fixture)
310
353
 
311
354
 
phoenix/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "4.25.0"
1
+ __version__ = "4.27.0"
phoenix/auth/__init__.py DELETED
File without changes
phoenix/auth/utils.py DELETED
@@ -1,15 +0,0 @@
1
- from hashlib import pbkdf2_hmac
2
-
3
-
4
- def compute_password_hash(password: str, salt: str) -> str:
5
- """
6
- Salts and hashes a password using PBKDF2, HMAC, and SHA256.
7
- """
8
- password_bytes = password.encode("utf-8")
9
- salt_bytes = salt.encode("utf-8")
10
- password_hash_bytes = pbkdf2_hmac("sha256", password_bytes, salt_bytes, NUM_ITERATIONS)
11
- password_hash = password_hash_bytes.hex()
12
- return password_hash
13
-
14
-
15
- NUM_ITERATIONS = 1_000_000
@@ -1,100 +0,0 @@
1
- import{r as d,j as e,d3 as P,v as s,F,R as v,w as E,aP as S,d4 as L,d5 as R,d6 as a,d7 as w,d8 as z,b as A,d9 as j}from"./vendor-aSQri0vz.js";import{S as C,j as k,Z as $,U as _,t as I,a4 as O}from"./vendor-arizeai-CsdcB1NH.js";import{L as T,E as D,h as N,M as G,a as m,D as M,d as U,b as B,e as q,P as J,c as K,T as W,p as H,f as u,g as V,i as Y,j as g,k as Z,l as h,m as b,n as Q,o as X,q as ee,r as re,s as ae,A as te,S as oe,F as ne}from"./pages-CFS6mPnW.js";import{b3 as se,d as ie,R as le,b4 as ce,b5 as de}from"./components-1Ahruijo.js";import"./vendor-three-DwGkEfCM.js";import"./vendor-recharts-B0sannek.js";import"./vendor-codemirror-CYHkhs7D.js";(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))c(t);new MutationObserver(t=>{for(const o of t)if(o.type==="childList")for(const i of o.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&c(i)}).observe(document,{childList:!0,subtree:!0});function l(t){const o={};return t.integrity&&(o.integrity=t.integrity),t.referrerPolicy&&(o.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?o.credentials="include":t.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function c(t){if(t.ep)return;t.ep=!0;const o=l(t);fetch(t.href,o)}})();const x="arize-phoenix-feature-flags",p={__CLEAR__:!0};function pe(){const r=localStorage.getItem(x);if(!r)return p;try{const n=JSON.parse(r);return Object.assign({},p,n)}catch{return p}}const f=d.createContext(null);function me(){const r=v.useContext(f);if(r===null)throw new Error("useFeatureFlags must be used within a FeatureFlagsProvider");return r}function ue(r){const[n,l]=d.useState(pe()),c=t=>{localStorage.setItem(x,JSON.stringify(t)),l(t)};return e(f.Provider,{value:{featureFlags:n,setFeatureFlags:c},children:e(ge,{children:r.children})})}function ge(r){const{children:n}=r,{featureFlags:l,setFeatureFlags:c}=me(),[t,o]=d.useState(!1);return P("ctrl+shift+f",()=>o(!0)),s(F,{children:[n,e(_,{type:"modal",isDismissable:!0,onDismiss:()=>o(!1),children:t&&e(C,{title:"Feature Flags",children:e(k,{height:"size-1000",padding:"size-100",children:Object.keys(l).map(i=>e($,{isSelected:l[i],onChange:y=>c({...l,[i]:y}),children:i},i))})})})]})}function he(){return e(S,{styles:r=>E`
2
- body {
3
- background-color: var(--ac-global-color-grey-75);
4
- color: var(--ac-global-text-color-900);
5
- font-family: "Roboto";
6
- font-size: ${r.typography.sizes.medium.fontSize}px;
7
- margin: 0;
8
- #root,
9
- #root > div[data-overlay-container="true"],
10
- #root > div[data-overlay-container="true"] > .ac-theme {
11
- height: 100vh;
12
- }
13
- }
14
-
15
- /* Remove list styling */
16
- ul {
17
- display: block;
18
- list-style-type: none;
19
- margin-block-start: none;
20
- margin-block-end: 0;
21
- padding-inline-start: 0;
22
- margin-block-start: 0;
23
- }
24
-
25
- /* A reset style for buttons */
26
- .button--reset {
27
- background: none;
28
- border: none;
29
- padding: 0;
30
- }
31
- /* this css class is added to html via modernizr @see modernizr.js */
32
- .no-hiddenscroll {
33
- /* Works on Firefox */
34
- * {
35
- scrollbar-width: thin;
36
- scrollbar-color: var(--ac-global-color-grey-300)
37
- var(--ac-global-color-grey-400);
38
- }
39
-
40
- /* Works on Chrome, Edge, and Safari */
41
- *::-webkit-scrollbar {
42
- width: 14px;
43
- }
44
-
45
- *::-webkit-scrollbar-track {
46
- background: var(--ac-global-color-grey-100);
47
- }
48
-
49
- *::-webkit-scrollbar-thumb {
50
- background-color: var(--ac-global-color-grey-75);
51
- border-radius: 8px;
52
- border: 1px solid var(--ac-global-color-grey-300);
53
- }
54
- }
55
-
56
- :root {
57
- --px-blue-color: ${r.colors.arizeBlue};
58
-
59
- --px-flex-gap-sm: ${r.spacing.margin4}px;
60
- --px-flex-gap-sm: ${r.spacing.margin8}px;
61
-
62
- --px-section-background-color: ${r.colors.gray500};
63
-
64
- /* An item is a typically something in a list */
65
- --px-item-background-color: ${r.colors.gray800};
66
- --px-item-border-color: ${r.colors.gray600};
67
-
68
- --px-spacing-sm: ${r.spacing.padding4}px;
69
- --px-spacing-med: ${r.spacing.padding8}px;
70
- --px-spacing-lg: ${r.spacing.padding16}px;
71
-
72
- --px-border-radius-med: ${r.borderRadius.medium}px;
73
-
74
- --px-font-size-sm: ${r.typography.sizes.small.fontSize}px;
75
- --px-font-size-med: ${r.typography.sizes.medium.fontSize}px;
76
- --px-font-size-lg: ${r.typography.sizes.large.fontSize}px;
77
-
78
- --px-gradient-bar-height: 8px;
79
-
80
- --px-nav-collapsed-width: 45px;
81
- --px-nav-expanded-width: 200px;
82
- }
83
-
84
- .ac-theme--dark {
85
- --px-primary-color: #9efcfd;
86
- --px-primary-color--transparent: rgb(158, 252, 253, 0.2);
87
- --px-reference-color: #baa1f9;
88
- --px-reference-color--transparent: #baa1f982;
89
- --px-corpus-color: #92969c;
90
- --px-corpus-color--transparent: #92969c63;
91
- }
92
- .ac-theme--light {
93
- --px-primary-color: #00add0;
94
- --px-primary-color--transparent: rgba(0, 173, 208, 0.2);
95
- --px-reference-color: #4500d9;
96
- --px-reference-color--transparent: rgba(69, 0, 217, 0.2);
97
- --px-corpus-color: #92969c;
98
- --px-corpus-color--transparent: #92969c63;
99
- }
100
- `})}const be=L(R(s(a,{path:"/",element:e(T,{}),errorElement:e(D,{}),children:[e(a,{index:!0,loader:N}),s(a,{path:"/model",handle:{crumb:()=>"model"},element:e(G,{}),children:[e(a,{index:!0,element:e(m,{})}),e(a,{element:e(m,{}),children:e(a,{path:"dimensions",children:e(a,{path:":dimensionId",element:e(M,{}),loader:U})})}),e(a,{path:"embeddings",children:e(a,{path:":embeddingDimensionId",element:e(B,{}),loader:q,handle:{crumb:r=>r.embedding.name}})})]}),s(a,{path:"/projects",handle:{crumb:()=>"projects"},element:e(J,{}),children:[e(a,{index:!0,element:e(K,{})}),s(a,{path:":projectId",element:e(W,{}),loader:H,handle:{crumb:r=>r.project.name},children:[e(a,{index:!0,element:e(u,{})}),e(a,{element:e(u,{}),children:e(a,{path:"traces/:traceId",element:e(V,{})})})]})]}),s(a,{path:"/datasets",handle:{crumb:()=>"datasets"},children:[e(a,{index:!0,element:e(Y,{})}),s(a,{path:":datasetId",loader:g,handle:{crumb:r=>r.dataset.name},children:[s(a,{element:e(Z,{}),loader:g,children:[e(a,{index:!0,element:e(h,{}),loader:b}),e(a,{path:"experiments",element:e(h,{}),loader:b}),e(a,{path:"examples",element:e(Q,{}),loader:X,children:e(a,{path:":exampleId",element:e(ee,{})})})]}),e(a,{path:"compare",handle:{crumb:()=>"compare"},loader:re,element:e(ae,{})})]})]}),e(a,{path:"/apis",element:e(te,{}),handle:{crumb:()=>"APIs"}}),e(a,{path:"/settings",element:e(oe,{}),handle:{crumb:()=>"Settings"}})]})),{basename:window.Config.basename});function xe(){return e(w,{router:be})}function fe(){return e(ne,{children:e(se,{children:e(ye,{})})})}function ye(){const{theme:r}=ie();return e(O,{theme:r,children:e(z,{theme:I,children:s(A.RelayEnvironmentProvider,{environment:le,children:[e(he,{}),e(ue,{children:e(ce,{children:e(d.Suspense,{children:e(de,{children:e(xe,{})})})})})]})})})}const Pe=document.getElementById("root"),Fe=j.createRoot(Pe);Fe.render(e(fe,{}));