arize-phoenix 4.12.1rc1__py3-none-any.whl → 4.15.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.

Files changed (73) hide show
  1. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.15.0.dist-info}/METADATA +10 -6
  2. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.15.0.dist-info}/RECORD +70 -68
  3. phoenix/db/bulk_inserter.py +5 -4
  4. phoenix/db/engines.py +2 -1
  5. phoenix/experiments/evaluators/base.py +4 -0
  6. phoenix/experiments/evaluators/code_evaluators.py +80 -0
  7. phoenix/experiments/evaluators/llm_evaluators.py +77 -1
  8. phoenix/experiments/evaluators/utils.py +70 -21
  9. phoenix/experiments/functions.py +17 -16
  10. phoenix/server/api/context.py +5 -3
  11. phoenix/server/api/dataloaders/__init__.py +2 -0
  12. phoenix/server/api/dataloaders/average_experiment_run_latency.py +25 -25
  13. phoenix/server/api/dataloaders/dataset_example_revisions.py +2 -4
  14. phoenix/server/api/dataloaders/dataset_example_spans.py +2 -4
  15. phoenix/server/api/dataloaders/document_evaluation_summaries.py +2 -4
  16. phoenix/server/api/dataloaders/document_evaluations.py +2 -4
  17. phoenix/server/api/dataloaders/document_retrieval_metrics.py +2 -4
  18. phoenix/server/api/dataloaders/evaluation_summaries.py +2 -4
  19. phoenix/server/api/dataloaders/experiment_annotation_summaries.py +2 -4
  20. phoenix/server/api/dataloaders/experiment_error_rates.py +32 -14
  21. phoenix/server/api/dataloaders/experiment_run_counts.py +20 -9
  22. phoenix/server/api/dataloaders/experiment_sequence_number.py +2 -4
  23. phoenix/server/api/dataloaders/latency_ms_quantile.py +2 -3
  24. phoenix/server/api/dataloaders/min_start_or_max_end_times.py +2 -4
  25. phoenix/server/api/dataloaders/project_by_name.py +3 -3
  26. phoenix/server/api/dataloaders/record_counts.py +2 -4
  27. phoenix/server/api/dataloaders/span_annotations.py +2 -4
  28. phoenix/server/api/dataloaders/span_dataset_examples.py +36 -0
  29. phoenix/server/api/dataloaders/span_descendants.py +2 -4
  30. phoenix/server/api/dataloaders/span_evaluations.py +2 -4
  31. phoenix/server/api/dataloaders/span_projects.py +3 -3
  32. phoenix/server/api/dataloaders/token_counts.py +2 -4
  33. phoenix/server/api/dataloaders/trace_evaluations.py +2 -4
  34. phoenix/server/api/dataloaders/trace_row_ids.py +2 -4
  35. phoenix/server/api/input_types/{CreateSpanAnnotationsInput.py → CreateSpanAnnotationInput.py} +4 -2
  36. phoenix/server/api/input_types/{CreateTraceAnnotationsInput.py → CreateTraceAnnotationInput.py} +4 -2
  37. phoenix/server/api/input_types/{PatchAnnotationsInput.py → PatchAnnotationInput.py} +4 -2
  38. phoenix/server/api/mutations/span_annotations_mutations.py +20 -9
  39. phoenix/server/api/mutations/trace_annotations_mutations.py +20 -9
  40. phoenix/server/api/routers/v1/datasets.py +132 -10
  41. phoenix/server/api/routers/v1/evaluations.py +3 -5
  42. phoenix/server/api/routers/v1/experiments.py +1 -1
  43. phoenix/server/api/types/Experiment.py +2 -2
  44. phoenix/server/api/types/Inferences.py +1 -2
  45. phoenix/server/api/types/Model.py +1 -2
  46. phoenix/server/api/types/Span.py +5 -0
  47. phoenix/server/api/utils.py +4 -4
  48. phoenix/server/app.py +21 -18
  49. phoenix/server/grpc_server.py +2 -2
  50. phoenix/server/main.py +5 -9
  51. phoenix/server/static/.vite/manifest.json +31 -31
  52. phoenix/server/static/assets/{components-C8sm_r1F.js → components-kGgeFkHp.js} +150 -110
  53. phoenix/server/static/assets/index-BctFO6S7.js +100 -0
  54. phoenix/server/static/assets/{pages-bN7juCjh.js → pages-DabDCmVd.js} +432 -255
  55. phoenix/server/static/assets/{vendor-CUDAPm8e.js → vendor-CP0b0YG0.js} +2 -2
  56. phoenix/server/static/assets/{vendor-arizeai-Do2HOmcL.js → vendor-arizeai-B5Hti8OB.js} +27 -27
  57. phoenix/server/static/assets/vendor-codemirror-DtdPDzrv.js +15 -0
  58. phoenix/server/static/assets/{vendor-recharts-PKRvByVe.js → vendor-recharts-A0DA1O99.js} +1 -1
  59. phoenix/server/types.py +18 -0
  60. phoenix/session/client.py +9 -6
  61. phoenix/session/session.py +2 -2
  62. phoenix/trace/dsl/filter.py +40 -25
  63. phoenix/trace/fixtures.py +17 -23
  64. phoenix/trace/utils.py +23 -0
  65. phoenix/utilities/client.py +116 -0
  66. phoenix/utilities/project.py +1 -1
  67. phoenix/version.py +1 -1
  68. phoenix/server/api/routers/v1/dataset_examples.py +0 -157
  69. phoenix/server/static/assets/index-BEKPzgQs.js +0 -100
  70. phoenix/server/static/assets/vendor-codemirror-CrdxOlMs.js +0 -12
  71. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.15.0.dist-info}/WHEEL +0 -0
  72. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.15.0.dist-info}/licenses/IP_NOTICE +0 -0
  73. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,116 @@
1
+ import warnings
2
+ from typing import Any
3
+
4
+ import httpx
5
+
6
+ PHOENIX_SERVER_VERSION_HEADER = "x-phoenix-server-version"
7
+
8
+
9
+ class VersionedClient(httpx.Client):
10
+ """
11
+ A httpx.Client wrapper that warns if there is a server/client version mismatch.
12
+ """
13
+
14
+ def __init__(self, *args: Any, **kwargs: Any):
15
+ from phoenix import __version__ as phoenix_version
16
+
17
+ super().__init__(*args, **kwargs)
18
+ self._client_phoenix_version = phoenix_version
19
+ self._warned_on_minor_version_mismatch = False
20
+
21
+ def _check_version(self, response: httpx.Response) -> None:
22
+ server_version = response.headers.get(PHOENIX_SERVER_VERSION_HEADER)
23
+
24
+ if server_version is None:
25
+ warnings.warn(
26
+ "The Phoenix server has an unknown version and may have compatibility issues."
27
+ )
28
+ return
29
+
30
+ try:
31
+ client_major, client_minor, client_patch = map(
32
+ int, self._client_phoenix_version.split(".")
33
+ )
34
+ server_major, server_minor, server_patch = map(int, server_version.split("."))
35
+ if abs(server_major - client_major) >= 1:
36
+ warnings.warn(
37
+ f"⚠️⚠️ The Phoenix server ({server_version}) and client "
38
+ f"({self._client_phoenix_version}) versions are severely mismatched. Upgrade "
39
+ " either the client or server to ensure API compatibility ⚠️⚠️"
40
+ )
41
+ elif (
42
+ abs(server_minor - client_minor) >= 1 and not self._warned_on_minor_version_mismatch
43
+ ):
44
+ self._warned_on_minor_version_mismatch = True
45
+ warnings.warn(
46
+ f"The Phoenix server ({server_version}) and client "
47
+ f"({self._client_phoenix_version}) versions are mismatched and may have "
48
+ "compatibility issues."
49
+ )
50
+ except ValueError:
51
+ # if either the client or server version includes a suffix e.g. "rc1", check for an
52
+ # exact version match of the version string
53
+ if self._client_phoenix_version != server_version:
54
+ warnings.warn(
55
+ f"The Phoenix server ({server_version}) and client "
56
+ f"({self._client_phoenix_version}) versions are mismatched and may have "
57
+ "compatibility issues."
58
+ )
59
+
60
+ def request(self, *args: Any, **kwargs: Any) -> httpx.Response:
61
+ response = super().request(*args, **kwargs)
62
+ self._check_version(response)
63
+ return response
64
+
65
+
66
+ class VersionedAsyncClient(httpx.AsyncClient):
67
+ """
68
+ A httpx.Client wrapper that warns if there is a server/client version mismatch.
69
+ """
70
+
71
+ def __init__(self, *args: Any, **kwargs: Any):
72
+ from phoenix import __version__ as phoenix_version
73
+
74
+ super().__init__(*args, **kwargs)
75
+ self._client_phoenix_version = phoenix_version
76
+ self._warned_on_minor_version_mismatch = False
77
+
78
+ def _check_version(self, response: httpx.Response) -> None:
79
+ server_version = response.headers.get(PHOENIX_SERVER_VERSION_HEADER)
80
+
81
+ if server_version is None:
82
+ return
83
+
84
+ try:
85
+ client_major, client_minor, client_patch = map(
86
+ int, self._client_phoenix_version.split(".")
87
+ )
88
+ server_major, server_minor, server_patch = map(int, server_version.split("."))
89
+ if abs(server_major - client_major) >= 1:
90
+ warnings.warn(
91
+ f"⚠️⚠️ The Phoenix server ({server_version}) and client "
92
+ f"({self._client_phoenix_version}) versions are severely mismatched. Upgrade "
93
+ " either the client or server to ensure API compatibility ⚠️⚠️"
94
+ )
95
+ elif (
96
+ abs(server_minor - client_minor) >= 1 and not self._warned_on_minor_version_mismatch
97
+ ):
98
+ self._warned_on_minor_version_mismatch = True
99
+ warnings.warn(
100
+ f"The Phoenix server ({server_version}) and client "
101
+ f"({self._client_phoenix_version}) versions are mismatched and may have "
102
+ "compatibility issues."
103
+ )
104
+ except ValueError:
105
+ # if the version includes a suffix e.g. "rc1", check for an exact version match
106
+ if self._client_phoenix_version != server_version:
107
+ warnings.warn(
108
+ f"The Phoenix server ({server_version}) and client "
109
+ f"({self._client_phoenix_version}) versions are mismatched and may have "
110
+ "compatibility issues."
111
+ )
112
+
113
+ async def request(self, *args: Any, **kwargs: Any) -> httpx.Response:
114
+ response = await super().request(*args, **kwargs)
115
+ self._check_version(response)
116
+ return response
@@ -9,5 +9,5 @@ from phoenix.config import DEFAULT_PROJECT_NAME
9
9
  def get_project_name(attributes: Iterable[KeyValue]) -> str:
10
10
  for kv in attributes:
11
11
  if kv.key == ResourceAttributes.PROJECT_NAME and (v := kv.value.string_value):
12
- return v
12
+ return str(v)
13
13
  return DEFAULT_PROJECT_NAME
phoenix/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "4.12.1rc1"
1
+ __version__ = "4.15.0"
@@ -1,157 +0,0 @@
1
- from datetime import datetime
2
- from typing import Any, Dict, List, Optional
3
-
4
- from fastapi import APIRouter, HTTPException, Path, Query
5
- from sqlalchemy import and_, func, select
6
- from starlette.requests import Request
7
- from starlette.status import HTTP_404_NOT_FOUND
8
- from strawberry.relay import GlobalID
9
-
10
- from phoenix.db.models import (
11
- Dataset as ORMDataset,
12
- )
13
- from phoenix.db.models import (
14
- DatasetExample as ORMDatasetExample,
15
- )
16
- from phoenix.db.models import (
17
- DatasetExampleRevision as ORMDatasetExampleRevision,
18
- )
19
- from phoenix.db.models import (
20
- DatasetVersion as ORMDatasetVersion,
21
- )
22
-
23
- from .pydantic_compat import V1RoutesBaseModel
24
- from .utils import ResponseBody, add_errors_to_responses
25
-
26
- router = APIRouter(tags=["datasets"])
27
-
28
-
29
- class DatasetExample(V1RoutesBaseModel):
30
- id: str
31
- input: Dict[str, Any]
32
- output: Dict[str, Any]
33
- metadata: Dict[str, Any]
34
- updated_at: datetime
35
-
36
-
37
- class ListDatasetExamplesData(V1RoutesBaseModel):
38
- dataset_id: str
39
- version_id: str
40
- examples: List[DatasetExample]
41
-
42
-
43
- class ListDatasetExamplesResponseBody(ResponseBody[ListDatasetExamplesData]):
44
- pass
45
-
46
-
47
- @router.get(
48
- "/datasets/{id}/examples",
49
- operation_id="getDatasetExamples",
50
- summary="Get examples from a dataset",
51
- responses=add_errors_to_responses([HTTP_404_NOT_FOUND]),
52
- )
53
- async def get_dataset_examples(
54
- request: Request,
55
- id: str = Path(description="The ID of the dataset"),
56
- version_id: Optional[str] = Query(
57
- default=None,
58
- description=(
59
- "The ID of the dataset version " "(if omitted, returns data from the latest version)"
60
- ),
61
- ),
62
- ) -> ListDatasetExamplesResponseBody:
63
- dataset_gid = GlobalID.from_id(id)
64
- version_gid = GlobalID.from_id(version_id) if version_id else None
65
-
66
- if (dataset_type := dataset_gid.type_name) != "Dataset":
67
- raise HTTPException(
68
- detail=f"ID {dataset_gid} refers to a {dataset_type}", status_code=HTTP_404_NOT_FOUND
69
- )
70
-
71
- if version_gid and (version_type := version_gid.type_name) != "DatasetVersion":
72
- raise HTTPException(
73
- detail=f"ID {version_gid} refers to a {version_type}", status_code=HTTP_404_NOT_FOUND
74
- )
75
-
76
- async with request.app.state.db() as session:
77
- if (
78
- resolved_dataset_id := await session.scalar(
79
- select(ORMDataset.id).where(ORMDataset.id == int(dataset_gid.node_id))
80
- )
81
- ) is None:
82
- raise HTTPException(
83
- detail=f"No dataset with id {dataset_gid} can be found.",
84
- status_code=HTTP_404_NOT_FOUND,
85
- )
86
-
87
- # Subquery to find the maximum created_at for each dataset_example_id
88
- # timestamp tiebreaks are resolved by the largest id
89
- partial_subquery = select(
90
- func.max(ORMDatasetExampleRevision.id).label("max_id"),
91
- ).group_by(ORMDatasetExampleRevision.dataset_example_id)
92
-
93
- if version_gid:
94
- if (
95
- resolved_version_id := await session.scalar(
96
- select(ORMDatasetVersion.id).where(
97
- and_(
98
- ORMDatasetVersion.dataset_id == resolved_dataset_id,
99
- ORMDatasetVersion.id == int(version_gid.node_id),
100
- )
101
- )
102
- )
103
- ) is None:
104
- raise HTTPException(
105
- detail=f"No dataset version with id {version_id} can be found.",
106
- status_code=HTTP_404_NOT_FOUND,
107
- )
108
- # if a version_id is provided, filter the subquery to only include revisions from that
109
- partial_subquery = partial_subquery.filter(
110
- ORMDatasetExampleRevision.dataset_version_id <= resolved_version_id
111
- )
112
- else:
113
- if (
114
- resolved_version_id := await session.scalar(
115
- select(func.max(ORMDatasetVersion.id)).where(
116
- ORMDatasetVersion.dataset_id == resolved_dataset_id
117
- )
118
- )
119
- ) is None:
120
- raise HTTPException(
121
- detail="Dataset has no versions.",
122
- status_code=HTTP_404_NOT_FOUND,
123
- )
124
-
125
- subquery = partial_subquery.subquery()
126
- # Query for the most recent example revisions that are not deleted
127
- query = (
128
- select(ORMDatasetExample, ORMDatasetExampleRevision)
129
- .join(
130
- ORMDatasetExampleRevision,
131
- ORMDatasetExample.id == ORMDatasetExampleRevision.dataset_example_id,
132
- )
133
- .join(
134
- subquery,
135
- (subquery.c.max_id == ORMDatasetExampleRevision.id),
136
- )
137
- .filter(ORMDatasetExample.dataset_id == resolved_dataset_id)
138
- .filter(ORMDatasetExampleRevision.revision_kind != "DELETE")
139
- .order_by(ORMDatasetExample.id.asc())
140
- )
141
- examples = [
142
- DatasetExample(
143
- id=str(GlobalID("DatasetExample", str(example.id))),
144
- input=revision.input,
145
- output=revision.output,
146
- metadata=revision.metadata_,
147
- updated_at=revision.created_at,
148
- )
149
- async for example, revision in await session.stream(query)
150
- ]
151
- return ListDatasetExamplesResponseBody(
152
- data=ListDatasetExamplesData(
153
- dataset_id=str(GlobalID("Dataset", str(resolved_dataset_id))),
154
- version_id=str(GlobalID("DatasetVersion", str(resolved_version_id))),
155
- examples=examples,
156
- )
157
- )
@@ -1,100 +0,0 @@
1
- import{r as d,j as e,d2 as F,v as s,F as P,R as v,w as E,aN as L,d3 as R,d4 as S,d5 as a,d6 as w,d7 as z,b as A,d8 as j}from"./vendor-CUDAPm8e.js";import{Q as C,j as k,Y as _,S as $,t as I,a4 as O}from"./vendor-arizeai-Do2HOmcL.js";import{aY as D,d as T,R as N,aZ as G,a_ as M}from"./components-C8sm_r1F.js";import{L as B,E as U,h as Y,M as q,a as m,D as J,d as K,b as W,e as H,P as Q,c as V,f as Z,p as X,g as u,i as ee,j as re,k as g,l as ae,m as h,n as f,o as oe,q as te,r as ne,s as se,t as le,A as ie}from"./pages-bN7juCjh.js";import"./vendor-three-DwGkEfCM.js";import"./vendor-codemirror-CrdxOlMs.js";import"./vendor-recharts-PKRvByVe.js";(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))c(o);new MutationObserver(o=>{for(const t of o)if(t.type==="childList")for(const l of t.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&c(l)}).observe(document,{childList:!0,subtree:!0});function i(o){const t={};return o.integrity&&(t.integrity=o.integrity),o.referrerPolicy&&(t.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?t.credentials="include":o.crossOrigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function c(o){if(o.ep)return;o.ep=!0;const t=i(o);fetch(o.href,t)}})();const x="arize-phoenix-feature-flags",p={__CLEAR__:!1};function ce(){const r=localStorage.getItem(x);if(!r)return p;try{const n=JSON.parse(r);return Object.assign({},p,n)}catch{return p}}const b=d.createContext(null);function de(){const r=v.useContext(b);if(r===null)throw new Error("useFeatureFlags must be used within a FeatureFlagsProvider");return r}function pe(r){const[n,i]=d.useState(ce()),c=o=>{localStorage.setItem(x,JSON.stringify(o)),i(o)};return e(b.Provider,{value:{featureFlags:n,setFeatureFlags:c},children:e(me,{children:r.children})})}function me(r){const{children:n}=r,{featureFlags:i,setFeatureFlags:c}=de(),[o,t]=d.useState(!1);return F("ctrl+shift+f",()=>t(!0)),s(P,{children:[n,e($,{type:"modal",isDismissable:!0,onDismiss:()=>t(!1),children:o&&e(C,{title:"Feature Flags",children:e(k,{height:"size-1000",padding:"size-100",children:Object.keys(i).map(l=>e(_,{isSelected:i[l],onChange:y=>c({...i,[l]:y}),children:l},l))})})})]})}function ue(){return e(L,{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 ge=R(S(s(a,{path:"/",element:e(B,{}),errorElement:e(U,{}),children:[e(a,{index:!0,loader:Y}),s(a,{path:"/model",handle:{crumb:()=>"model"},element:e(q,{}),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(J,{}),loader:K})})}),e(a,{path:"embeddings",children:e(a,{path:":embeddingDimensionId",element:e(W,{}),loader:H,handle:{crumb:r=>r.embedding.name}})})]}),s(a,{path:"/projects",handle:{crumb:()=>"projects"},element:e(Q,{}),children:[e(a,{index:!0,element:e(V,{})}),s(a,{path:":projectId",element:e(Z,{}),loader:X,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(ee,{})})})]})]}),s(a,{path:"/datasets",handle:{crumb:()=>"datasets"},children:[e(a,{index:!0,element:e(re,{})}),s(a,{path:":datasetId",loader:g,handle:{crumb:r=>r.dataset.name},children:[s(a,{element:e(ae,{}),loader:g,children:[e(a,{index:!0,element:e(h,{}),loader:f}),e(a,{path:"experiments",element:e(h,{}),loader:f}),e(a,{path:"examples",element:e(oe,{}),loader:te,children:e(a,{path:":exampleId",element:e(ne,{})})})]}),e(a,{path:"compare",handle:{crumb:()=>"compare"},loader:se,element:e(le,{})})]})]}),e(a,{path:"/apis",element:e(ie,{}),handle:{crumb:()=>"APIs"}})]})),{basename:window.Config.basename});function he(){return e(w,{router:ge})}function fe(){return e(D,{children:e(xe,{})})}function xe(){const{theme:r}=T();return e(O,{theme:r,children:e(z,{theme:I,children:s(A.RelayEnvironmentProvider,{environment:N,children:[e(ue,{}),e(pe,{children:e(G,{children:e(d.Suspense,{children:e(M,{children:e(he,{})})})})})]})})})}const be=document.getElementById("root"),ye=j.createRoot(be);ye.render(e(fe,{}));