arize-phoenix 4.12.1rc1__py3-none-any.whl → 4.14.1__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 (51) hide show
  1. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.14.1.dist-info}/METADATA +12 -9
  2. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.14.1.dist-info}/RECORD +48 -49
  3. phoenix/db/bulk_inserter.py +3 -1
  4. phoenix/experiments/evaluators/base.py +4 -0
  5. phoenix/experiments/evaluators/code_evaluators.py +80 -0
  6. phoenix/experiments/evaluators/llm_evaluators.py +77 -1
  7. phoenix/experiments/evaluators/utils.py +70 -21
  8. phoenix/experiments/functions.py +14 -14
  9. phoenix/server/api/context.py +7 -3
  10. phoenix/server/api/dataloaders/average_experiment_run_latency.py +23 -23
  11. phoenix/server/api/dataloaders/experiment_error_rates.py +30 -10
  12. phoenix/server/api/dataloaders/experiment_run_counts.py +18 -5
  13. phoenix/server/api/input_types/{CreateSpanAnnotationsInput.py → CreateSpanAnnotationInput.py} +4 -2
  14. phoenix/server/api/input_types/{CreateTraceAnnotationsInput.py → CreateTraceAnnotationInput.py} +4 -2
  15. phoenix/server/api/input_types/{PatchAnnotationsInput.py → PatchAnnotationInput.py} +4 -2
  16. phoenix/server/api/mutations/span_annotations_mutations.py +12 -6
  17. phoenix/server/api/mutations/trace_annotations_mutations.py +12 -6
  18. phoenix/server/api/openapi/main.py +2 -18
  19. phoenix/server/api/openapi/schema.py +12 -12
  20. phoenix/server/api/routers/v1/__init__.py +83 -36
  21. phoenix/server/api/routers/v1/dataset_examples.py +123 -102
  22. phoenix/server/api/routers/v1/datasets.py +506 -390
  23. phoenix/server/api/routers/v1/evaluations.py +66 -73
  24. phoenix/server/api/routers/v1/experiment_evaluations.py +91 -68
  25. phoenix/server/api/routers/v1/experiment_runs.py +155 -98
  26. phoenix/server/api/routers/v1/experiments.py +181 -132
  27. phoenix/server/api/routers/v1/spans.py +173 -144
  28. phoenix/server/api/routers/v1/traces.py +128 -115
  29. phoenix/server/api/types/Experiment.py +2 -2
  30. phoenix/server/api/types/Inferences.py +1 -2
  31. phoenix/server/api/types/Model.py +1 -2
  32. phoenix/server/app.py +177 -152
  33. phoenix/server/openapi/docs.py +221 -0
  34. phoenix/server/static/.vite/manifest.json +31 -31
  35. phoenix/server/static/assets/{components-C8sm_r1F.js → components-DeS0YEmv.js} +2 -2
  36. phoenix/server/static/assets/index-CQgXRwU0.js +100 -0
  37. phoenix/server/static/assets/{pages-bN7juCjh.js → pages-hdjlFZhO.js} +275 -198
  38. phoenix/server/static/assets/{vendor-CUDAPm8e.js → vendor-DPvSDRn3.js} +1 -1
  39. phoenix/server/static/assets/{vendor-arizeai-Do2HOmcL.js → vendor-arizeai-CkvPT67c.js} +2 -2
  40. phoenix/server/static/assets/{vendor-codemirror-CrdxOlMs.js → vendor-codemirror-Cqwpwlua.js} +1 -1
  41. phoenix/server/static/assets/{vendor-recharts-PKRvByVe.js → vendor-recharts-5jlNaZuF.js} +1 -1
  42. phoenix/server/thread_server.py +2 -2
  43. phoenix/session/client.py +9 -8
  44. phoenix/trace/dsl/filter.py +40 -25
  45. phoenix/version.py +1 -1
  46. phoenix/server/api/routers/v1/pydantic_compat.py +0 -78
  47. phoenix/server/api/routers/v1/utils.py +0 -95
  48. phoenix/server/static/assets/index-BEKPzgQs.js +0 -100
  49. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.14.1.dist-info}/WHEEL +0 -0
  50. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.14.1.dist-info}/licenses/IP_NOTICE +0 -0
  51. {arize_phoenix-4.12.1rc1.dist-info → arize_phoenix-4.14.1.dist-info}/licenses/LICENSE +0 -0
@@ -5,8 +5,8 @@ import typing
5
5
  from dataclasses import dataclass, field
6
6
  from difflib import SequenceMatcher
7
7
  from itertools import chain
8
- from random import randint
9
8
  from types import MappingProxyType
9
+ from uuid import uuid4
10
10
 
11
11
  import sqlalchemy
12
12
  from sqlalchemy.orm import Mapped, aliased
@@ -22,11 +22,14 @@ _VALID_EVAL_ATTRIBUTES: typing.Tuple[str, ...] = tuple(
22
22
  )
23
23
 
24
24
 
25
- EvalAttribute: TypeAlias = typing.Literal["label", "score"]
26
- EvalExpression: TypeAlias = str
27
- EvalName: TypeAlias = str
25
+ AnnotationType: TypeAlias = typing.Literal["annotations", "evals"]
26
+ AnnotationAttribute: TypeAlias = typing.Literal["label", "score"]
27
+ AnnotationExpression: TypeAlias = str
28
+ AnnotationName: TypeAlias = str
28
29
 
29
- EVAL_EXPRESSION_PATTERN = re.compile(r"""\b(evals\[(".*?"|'.*?')\][.](label|score))\b""")
30
+ EVAL_EXPRESSION_PATTERN = re.compile(
31
+ r"""\b((annotations|evals)\[(".*?"|'.*?')\][.](label|score))\b"""
32
+ )
30
33
 
31
34
 
32
35
  @dataclass(frozen=True)
@@ -46,9 +49,10 @@ class AliasedAnnotationRelation:
46
49
 
47
50
  def __post_init__(self) -> None:
48
51
  table_alias = f"span_annotation_{self.index}"
49
- alias_id = f"{randint(0, 10**6):06d}" # prevent conflicts with user-defined attributes
52
+ alias_id = uuid4().hex
50
53
  label_attribute_alias = f"{table_alias}_label_{alias_id}"
51
54
  score_attribute_alias = f"{table_alias}_score_{alias_id}"
55
+
52
56
  table = aliased(models.SpanAnnotation, name=table_alias)
53
57
  object.__setattr__(self, "_label_attribute_alias", label_attribute_alias)
54
58
  object.__setattr__(self, "_score_attribute_alias", score_attribute_alias)
@@ -67,7 +71,7 @@ class AliasedAnnotationRelation:
67
71
  yield self._label_attribute_alias, self.table.label
68
72
  yield self._score_attribute_alias, self.table.score
69
73
 
70
- def attribute_alias(self, attribute: EvalAttribute) -> str:
74
+ def attribute_alias(self, attribute: AnnotationAttribute) -> str:
71
75
  """
72
76
  Returns an alias for the given attribute (i.e., column).
73
77
  """
@@ -579,7 +583,7 @@ def _validate_expression(
579
583
  _is_subscript(node, "metadata") or _is_subscript(node, "attributes")
580
584
  ) and _get_attribute_keys_list(node) is not None:
581
585
  continue
582
- elif _is_eval(node) and _get_subscript_key(node) is not None:
586
+ elif _is_annotation(node) and _get_subscript_key(node) is not None:
583
587
  # e.g. `evals["name"]`
584
588
  if not (eval_name := _get_subscript_key(node)) or (
585
589
  valid_eval_names is not None and eval_name not in valid_eval_names
@@ -601,7 +605,7 @@ def _validate_expression(
601
605
  else ""
602
606
  )
603
607
  continue
604
- elif isinstance(node, ast.Attribute) and _is_eval(node.value):
608
+ elif isinstance(node, ast.Attribute) and _is_annotation(node.value):
605
609
  # e.g. `evals["name"].score`
606
610
  if (attr := node.attr) not in valid_eval_attributes:
607
611
  source_segment = typing.cast(str, ast.get_source_segment(source, node))
@@ -662,19 +666,19 @@ def _as_attribute(
662
666
  ) -> ast.Subscript:
663
667
  return ast.Subscript(
664
668
  value=ast.Name(id="attributes", ctx=ast.Load()),
665
- slice=ast.List(elts=keys, ctx=ast.Load())
669
+ slice=ast.List(elts=keys, ctx=ast.Load()) # type: ignore[arg-type]
666
670
  if sys.version_info >= (3, 9)
667
- else ast.Index(value=ast.List(elts=keys, ctx=ast.Load())),
671
+ else ast.Index(value=ast.List(elts=keys, ctx=ast.Load())), # type: ignore
668
672
  ctx=ast.Load(),
669
673
  )
670
674
 
671
675
 
672
- def _is_eval(node: typing.Any) -> TypeGuard[ast.Subscript]:
676
+ def _is_annotation(node: typing.Any) -> TypeGuard[ast.Subscript]:
673
677
  # e.g. `evals["name"]`
674
678
  return (
675
679
  isinstance(node, ast.Subscript)
676
680
  and isinstance(value := node.value, ast.Name)
677
- and value.id == "evals"
681
+ and value.id in ["evals", "annotations"]
678
682
  )
679
683
 
680
684
 
@@ -817,34 +821,45 @@ def _apply_eval_aliasing(
817
821
  span_annotation_0_label_123 == 'correct' or span_annotation_0_score_456 < 0.5
818
822
  ```
819
823
  """
820
- eval_aliases: typing.Dict[EvalName, AliasedAnnotationRelation] = {}
821
- for eval_expression, eval_name, eval_attribute in _parse_eval_expressions_and_names(source):
822
- if (eval_alias := eval_aliases.get(eval_name)) is None:
823
- eval_alias = AliasedAnnotationRelation(index=len(eval_aliases), name=eval_name)
824
- eval_aliases[eval_name] = eval_alias
825
- alias_name = eval_alias.attribute_alias(eval_attribute)
826
- source = source.replace(eval_expression, alias_name)
824
+ eval_aliases: typing.Dict[AnnotationName, AliasedAnnotationRelation] = {}
825
+ for (
826
+ annotation_expression,
827
+ annotation_type,
828
+ annotation_name,
829
+ annotation_attribute,
830
+ ) in _parse_annotation_expressions_and_names(source):
831
+ if (eval_alias := eval_aliases.get(annotation_name)) is None:
832
+ eval_alias = AliasedAnnotationRelation(index=len(eval_aliases), name=annotation_name)
833
+ eval_aliases[annotation_name] = eval_alias
834
+ alias_name = eval_alias.attribute_alias(annotation_attribute)
835
+ source = source.replace(annotation_expression, alias_name)
827
836
  return source, tuple(eval_aliases.values())
828
837
 
829
838
 
830
- def _parse_eval_expressions_and_names(
839
+ def _parse_annotation_expressions_and_names(
831
840
  source: str,
832
- ) -> typing.Iterator[typing.Tuple[EvalExpression, EvalName, EvalAttribute]]:
841
+ ) -> typing.Iterator[
842
+ typing.Tuple[AnnotationExpression, AnnotationType, AnnotationName, AnnotationAttribute]
843
+ ]:
833
844
  """
834
845
  Parses filter conditions for evaluation expressions of the form:
835
846
 
836
847
  ```
837
848
  evals["<eval-name>"].<attribute>
849
+ annotations["eval-name"].<attribute>
838
850
  ```
839
851
  """
840
852
  for match in EVAL_EXPRESSION_PATTERN.finditer(source):
841
853
  (
842
- eval_expression,
854
+ annotation_expression,
855
+ annotation_type,
843
856
  quoted_eval_name,
844
857
  evaluation_attribute_name,
845
858
  ) = match.groups()
859
+ annotation_type = typing.cast(AnnotationType, annotation_type)
846
860
  yield (
847
- eval_expression,
861
+ annotation_expression,
862
+ annotation_type,
848
863
  quoted_eval_name[1:-1],
849
- typing.cast(EvalAttribute, evaluation_attribute_name),
864
+ typing.cast(AnnotationAttribute, evaluation_attribute_name),
850
865
  )
phoenix/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "4.12.1rc1"
1
+ __version__ = "4.14.1"
@@ -1,78 +0,0 @@
1
- from datetime import datetime
2
- from enum import Enum
3
- from importlib.metadata import PackageNotFoundError, version
4
-
5
- from pydantic import BaseModel
6
- from typing_extensions import assert_never
7
-
8
-
9
- def datetime_encoder(dt: datetime) -> str:
10
- """
11
- Encodes a `datetime` object to an ISO-formatted timestamp string.
12
-
13
- By default, Pydantic v2 serializes `datetime` objects in a format that
14
- cannot be parsed by `datetime.fromisoformat`. Adding this encoder to the
15
- `json_encoders` config for a Pydantic model ensures that the serialized
16
- `datetime` objects are parseable.
17
- """
18
- return dt.isoformat()
19
-
20
-
21
- class PydanticMajorVersion(Enum):
22
- """
23
- The major version of `pydantic`.
24
- """
25
-
26
- V1 = "v1"
27
- V2 = "v2"
28
-
29
-
30
- def get_pydantic_major_version() -> PydanticMajorVersion:
31
- """
32
- Returns the major version of `pydantic` or raises an error if `pydantic` is
33
- not installed.
34
- """
35
- try:
36
- pydantic_version = version("pydantic")
37
- except PackageNotFoundError:
38
- raise RuntimeError("Please install pydantic with `pip install pydantic`.")
39
- if pydantic_version.startswith("1"):
40
- return PydanticMajorVersion.V1
41
- elif pydantic_version.startswith("2"):
42
- return PydanticMajorVersion.V2
43
- raise ValueError(f"Unsupported Pydantic version: {pydantic_version}")
44
-
45
-
46
- if (pydantic_major_version := get_pydantic_major_version()) is PydanticMajorVersion.V1:
47
-
48
- class V1RoutesBaseModel(BaseModel):
49
- class Config:
50
- json_encoders = {datetime: datetime_encoder}
51
-
52
- elif pydantic_major_version is PydanticMajorVersion.V2:
53
- from pydantic import ConfigDict
54
-
55
- # `json_encoders` is a configuration setting from Pydantic v1 that was
56
- # removed in Pydantic v2.0.* but restored in Pydantic v2.1.0 with a
57
- # deprecation warning. At this time, it remains the simplest way to
58
- # configure custom JSON serialization for specific data types in a manner
59
- # that is consistent between Pydantic v1 and v2.
60
- #
61
- # For details, see:
62
- # - https://github.com/pydantic/pydantic/pull/6811
63
- # - https://github.com/pydantic/pydantic/releases/tag/v2.1.0
64
- #
65
- # The assertion below is added in case a future release of Pydantic v2 fully
66
- # removes the `json_encoders` parameter.
67
- assert "json_encoders" in ConfigDict.__annotations__, (
68
- "If you encounter this error with `pydantic==2.0.*`, "
69
- "please upgrade `pydantic` with `pip install -U pydantic>=2.1.0`. "
70
- "If you encounter this error with `pydantic>=2.1.0`, "
71
- "please upgrade `arize-phoenix` with `pip install -U arize-phoenix`, "
72
- "or downgrade `pydantic` to a version that supports the `json_encoders` config setting."
73
- )
74
-
75
- class V1RoutesBaseModel(BaseModel): # type: ignore[no-redef]
76
- model_config = ConfigDict({"json_encoders": {datetime: datetime_encoder}})
77
- else:
78
- assert_never(pydantic_major_version)
@@ -1,95 +0,0 @@
1
- from typing import Any, Dict, Generic, List, Optional, TypedDict, Union
2
-
3
- from typing_extensions import TypeAlias, TypeVar, assert_never
4
-
5
- from .pydantic_compat import V1RoutesBaseModel
6
-
7
- StatusCode: TypeAlias = int
8
- DataType = TypeVar("DataType")
9
- Responses: TypeAlias = Dict[
10
- Union[int, str], Dict[str, Any]
11
- ] # input type for the `responses` parameter of a fastapi route
12
-
13
-
14
- class StatusCodeWithDescription(TypedDict):
15
- """
16
- A duck type for a status code with a description detailing under what
17
- conditions the status code is raised.
18
- """
19
-
20
- status_code: StatusCode
21
- description: str
22
-
23
-
24
- class RequestBody(V1RoutesBaseModel, Generic[DataType]):
25
- # A generic request type accepted by V1 routes.
26
- #
27
- # Don't use """ for this docstring or it will be included as a description
28
- # in the generated OpenAPI schema.
29
- data: DataType
30
-
31
-
32
- class ResponseBody(V1RoutesBaseModel, Generic[DataType]):
33
- # A generic response type returned by V1 routes.
34
- #
35
- # Don't use """ for this docstring or it will be included as a description
36
- # in the generated OpenAPI schema.
37
-
38
- data: DataType
39
-
40
-
41
- class PaginatedResponseBody(V1RoutesBaseModel, Generic[DataType]):
42
- # A generic paginated response type returned by V1 routes.
43
- #
44
- # Don't use """ for this docstring or it will be included as a description
45
- # in the generated OpenAPI schema.
46
-
47
- data: List[DataType]
48
- next_cursor: Optional[str]
49
-
50
-
51
- def add_errors_to_responses(
52
- errors: List[Union[StatusCode, StatusCodeWithDescription]],
53
- /,
54
- *,
55
- responses: Optional[Responses] = None,
56
- ) -> Responses:
57
- """
58
- Creates or updates a patch for an OpenAPI schema's `responses` section to
59
- include status codes in the generated OpenAPI schema.
60
- """
61
- output_responses: Responses = responses or {}
62
- for error in errors:
63
- status_code: int
64
- description: Optional[str] = None
65
- if isinstance(error, StatusCode):
66
- status_code = error
67
- elif isinstance(error, dict):
68
- status_code = error["status_code"]
69
- description = error["description"]
70
- else:
71
- assert_never(error)
72
- if status_code not in output_responses:
73
- output_responses[status_code] = {
74
- "content": {"text/plain": {"schema": {"type": "string"}}}
75
- }
76
- if description:
77
- output_responses[status_code]["description"] = description
78
- return output_responses
79
-
80
-
81
- def add_text_csv_content_to_responses(
82
- status_code: StatusCode, /, *, responses: Optional[Responses] = None
83
- ) -> Responses:
84
- """
85
- Creates or updates a patch for an OpenAPI schema's `responses` section to
86
- ensure that the response for the given status code is marked as text/csv in
87
- the generated OpenAPI schema.
88
- """
89
- output_responses: Responses = responses or {}
90
- if status_code not in output_responses:
91
- output_responses[status_code] = {}
92
- output_responses[status_code]["content"] = {
93
- "text/csv": {"schema": {"type": "string", "contentMediaType": "text/csv"}}
94
- }
95
- return output_responses
@@ -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,{}));