arize-phoenix 11.32.0__py3-none-any.whl → 11.33.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 (55) hide show
  1. {arize_phoenix-11.32.0.dist-info → arize_phoenix-11.33.0.dist-info}/METADATA +1 -1
  2. {arize_phoenix-11.32.0.dist-info → arize_phoenix-11.33.0.dist-info}/RECORD +49 -42
  3. phoenix/inferences/inferences.py +1 -2
  4. phoenix/server/api/context.py +20 -0
  5. phoenix/server/api/dataloaders/__init__.py +20 -0
  6. phoenix/server/api/dataloaders/average_experiment_repeated_run_group_latency.py +50 -0
  7. phoenix/server/api/dataloaders/dataset_example_revisions.py +0 -1
  8. phoenix/server/api/dataloaders/dataset_examples_and_versions_by_experiment_run.py +47 -0
  9. phoenix/server/api/dataloaders/experiment_repeated_run_group_annotation_summaries.py +77 -0
  10. phoenix/server/api/dataloaders/experiment_repeated_run_groups.py +59 -0
  11. phoenix/server/api/dataloaders/experiment_repetition_counts.py +39 -0
  12. phoenix/server/api/dataloaders/span_cost_summary_by_experiment_repeated_run_group.py +64 -0
  13. phoenix/server/api/helpers/playground_clients.py +4 -0
  14. phoenix/server/api/helpers/prompts/models.py +16 -18
  15. phoenix/server/api/mutations/prompt_label_mutations.py +67 -58
  16. phoenix/server/api/queries.py +52 -37
  17. phoenix/server/api/routers/v1/experiment_runs.py +1 -1
  18. phoenix/server/api/routers/v1/experiments.py +1 -1
  19. phoenix/server/api/types/DatasetExample.py +49 -1
  20. phoenix/server/api/types/Experiment.py +12 -2
  21. phoenix/server/api/types/ExperimentComparison.py +3 -9
  22. phoenix/server/api/types/ExperimentRepeatedRunGroup.py +146 -0
  23. phoenix/server/api/types/ExperimentRepeatedRunGroupAnnotationSummary.py +9 -0
  24. phoenix/server/api/types/ExperimentRun.py +12 -19
  25. phoenix/server/api/types/Prompt.py +11 -0
  26. phoenix/server/api/types/PromptLabel.py +2 -19
  27. phoenix/server/api/types/node.py +10 -0
  28. phoenix/server/app.py +22 -2
  29. phoenix/server/cost_tracking/model_cost_manifest.json +1 -1
  30. phoenix/server/static/.vite/manifest.json +43 -43
  31. phoenix/server/static/assets/components-YTHUASXI.js +5778 -0
  32. phoenix/server/static/assets/{index-D1FDMBMV.js → index-CugQp26L.js} +12 -21
  33. phoenix/server/static/assets/pages-4Qu8GNlt.js +9159 -0
  34. phoenix/server/static/assets/vendor-BGzfc4EU.css +1 -0
  35. phoenix/server/static/assets/vendor-CRRxHwSp.js +903 -0
  36. phoenix/server/static/assets/{vendor-arizeai-DsYDNOqt.js → vendor-arizeai-CUN6lRd9.js} +4 -4
  37. phoenix/server/static/assets/vendor-codemirror-sJXwoqrE.js +25 -0
  38. phoenix/server/static/assets/{vendor-recharts-BTHn5Y2R.js → vendor-recharts-BT_PeGhc.js} +2 -2
  39. phoenix/server/static/assets/{vendor-shiki-BAcocHFl.js → vendor-shiki-1F3op0QC.js} +1 -1
  40. phoenix/session/client.py +55 -1
  41. phoenix/session/data_extractor.py +5 -0
  42. phoenix/session/evaluation.py +8 -4
  43. phoenix/session/session.py +13 -0
  44. phoenix/trace/projects.py +1 -2
  45. phoenix/version.py +1 -1
  46. phoenix/server/static/assets/components-Cs9c4Nxp.js +0 -5698
  47. phoenix/server/static/assets/pages-Cbj9SjBx.js +0 -8928
  48. phoenix/server/static/assets/vendor-CqDb5u4o.css +0 -1
  49. phoenix/server/static/assets/vendor-RdRDaQiR.js +0 -905
  50. phoenix/server/static/assets/vendor-codemirror-BzJDUbEx.js +0 -25
  51. phoenix/utilities/deprecation.py +0 -31
  52. {arize_phoenix-11.32.0.dist-info → arize_phoenix-11.33.0.dist-info}/WHEEL +0 -0
  53. {arize_phoenix-11.32.0.dist-info → arize_phoenix-11.33.0.dist-info}/entry_points.txt +0 -0
  54. {arize_phoenix-11.32.0.dist-info → arize_phoenix-11.33.0.dist-info}/licenses/IP_NOTICE +0 -0
  55. {arize_phoenix-11.32.0.dist-info → arize_phoenix-11.33.0.dist-info}/licenses/LICENSE +0 -0
@@ -5,13 +5,14 @@ import strawberry
5
5
  from sqlalchemy import func, select
6
6
  from sqlalchemy.orm import joinedload
7
7
  from strawberry import UNSET, Private
8
- from strawberry.relay import Connection, Node, NodeID
8
+ from strawberry.relay import Connection, GlobalID, Node, NodeID
9
9
  from strawberry.scalars import JSON
10
10
  from strawberry.types import Info
11
11
 
12
12
  from phoenix.db import models
13
13
  from phoenix.server.api.context import Context
14
14
  from phoenix.server.api.types.CostBreakdown import CostBreakdown
15
+ from phoenix.server.api.types.DatasetVersion import DatasetVersion
15
16
  from phoenix.server.api.types.ExperimentAnnotationSummary import ExperimentAnnotationSummary
16
17
  from phoenix.server.api.types.ExperimentRun import ExperimentRun, to_gql_experiment_run
17
18
  from phoenix.server.api.types.pagination import (
@@ -32,6 +33,7 @@ class Experiment(Node):
32
33
  name: str
33
34
  project_name: Optional[str]
34
35
  description: Optional[str]
36
+ dataset_version_id: GlobalID
35
37
  metadata: JSON
36
38
  created_at: datetime
37
39
  updated_at: datetime
@@ -71,7 +73,10 @@ class Experiment(Node):
71
73
  await session.scalars(
72
74
  select(models.ExperimentRun)
73
75
  .where(models.ExperimentRun.experiment_id == experiment_id)
74
- .order_by(models.ExperimentRun.id.desc())
76
+ .order_by(
77
+ models.ExperimentRun.dataset_example_id.asc(),
78
+ models.ExperimentRun.repetition_number.asc(),
79
+ )
75
80
  .options(
76
81
  joinedload(models.ExperimentRun.trace).load_only(models.Trace.trace_id)
77
82
  )
@@ -187,6 +192,10 @@ class Experiment(Node):
187
192
  async for token_type, is_prompt, cost, tokens in data
188
193
  ]
189
194
 
195
+ @strawberry.field
196
+ async def repetition_count(self, info: Info[Context, None]) -> int:
197
+ return await info.context.data_loaders.experiment_repetition_counts.load(self.id_attr)
198
+
190
199
 
191
200
  def to_gql_experiment(
192
201
  experiment: models.Experiment,
@@ -201,6 +210,7 @@ def to_gql_experiment(
201
210
  name=experiment.name,
202
211
  project_name=experiment.project_name,
203
212
  description=experiment.description,
213
+ dataset_version_id=GlobalID(DatasetVersion.__name__, str(experiment.dataset_version_id)),
204
214
  metadata=experiment.metadata_,
205
215
  created_at=experiment.created_at,
206
216
  updated_at=experiment.updated_at,
@@ -1,18 +1,12 @@
1
1
  import strawberry
2
- from strawberry.relay import GlobalID, Node, NodeID
2
+ from strawberry.relay import Node, NodeID
3
3
 
4
4
  from phoenix.server.api.types.DatasetExample import DatasetExample
5
- from phoenix.server.api.types.ExperimentRun import ExperimentRun
6
-
7
-
8
- @strawberry.type
9
- class RunComparisonItem:
10
- experiment_id: GlobalID
11
- runs: list[ExperimentRun]
5
+ from phoenix.server.api.types.ExperimentRepeatedRunGroup import ExperimentRepeatedRunGroup
12
6
 
13
7
 
14
8
  @strawberry.type
15
9
  class ExperimentComparison(Node):
16
10
  id_attr: NodeID[int]
17
11
  example: DatasetExample
18
- run_comparison_items: list[RunComparisonItem]
12
+ repeated_run_groups: list[ExperimentRepeatedRunGroup]
@@ -0,0 +1,146 @@
1
+ import re
2
+ from base64 import b64decode
3
+ from typing import Optional
4
+
5
+ import strawberry
6
+ from sqlalchemy import func, select
7
+ from strawberry.relay import GlobalID, Node
8
+ from strawberry.types import Info
9
+ from typing_extensions import Self, TypeAlias
10
+
11
+ from phoenix.db import models
12
+ from phoenix.server.api.context import Context
13
+ from phoenix.server.api.types.CostBreakdown import CostBreakdown
14
+ from phoenix.server.api.types.ExperimentRepeatedRunGroupAnnotationSummary import (
15
+ ExperimentRepeatedRunGroupAnnotationSummary,
16
+ )
17
+ from phoenix.server.api.types.ExperimentRun import ExperimentRun
18
+ from phoenix.server.api.types.SpanCostDetailSummaryEntry import SpanCostDetailSummaryEntry
19
+ from phoenix.server.api.types.SpanCostSummary import SpanCostSummary
20
+
21
+ ExperimentRowId: TypeAlias = int
22
+ DatasetExampleRowId: TypeAlias = int
23
+
24
+
25
+ @strawberry.type
26
+ class ExperimentRepeatedRunGroup(Node):
27
+ experiment_rowid: strawberry.Private[ExperimentRowId]
28
+ dataset_example_rowid: strawberry.Private[DatasetExampleRowId]
29
+ runs: list[ExperimentRun]
30
+
31
+ @classmethod
32
+ def resolve_id(
33
+ cls,
34
+ root: Self,
35
+ *,
36
+ info: Info,
37
+ ) -> str:
38
+ return (
39
+ f"experiment_id={root.experiment_rowid}:dataset_example_id={root.dataset_example_rowid}"
40
+ )
41
+
42
+ @strawberry.field
43
+ def experiment_id(self) -> strawberry.ID:
44
+ from phoenix.server.api.types.Experiment import Experiment
45
+
46
+ return strawberry.ID(str(GlobalID(Experiment.__name__, str(self.experiment_rowid))))
47
+
48
+ @strawberry.field
49
+ async def average_latency_ms(self, info: Info[Context, None]) -> Optional[float]:
50
+ return await info.context.data_loaders.average_experiment_repeated_run_group_latency.load(
51
+ (self.experiment_rowid, self.dataset_example_rowid)
52
+ )
53
+
54
+ @strawberry.field
55
+ async def cost_summary(self, info: Info[Context, None]) -> SpanCostSummary:
56
+ experiment_id = self.experiment_rowid
57
+ example_id = self.dataset_example_rowid
58
+ summary = (
59
+ await info.context.data_loaders.span_cost_summary_by_experiment_repeated_run_group.load(
60
+ (experiment_id, example_id)
61
+ )
62
+ )
63
+ return SpanCostSummary(
64
+ prompt=CostBreakdown(
65
+ tokens=summary.prompt.tokens,
66
+ cost=summary.prompt.cost,
67
+ ),
68
+ completion=CostBreakdown(
69
+ tokens=summary.completion.tokens,
70
+ cost=summary.completion.cost,
71
+ ),
72
+ total=CostBreakdown(
73
+ tokens=summary.total.tokens,
74
+ cost=summary.total.cost,
75
+ ),
76
+ )
77
+
78
+ @strawberry.field
79
+ async def cost_detail_summary_entries(
80
+ self, info: Info[Context, None]
81
+ ) -> list[SpanCostDetailSummaryEntry]:
82
+ experiment_id = self.experiment_rowid
83
+ example_id = self.dataset_example_rowid
84
+ stmt = (
85
+ select(
86
+ models.SpanCostDetail.token_type,
87
+ models.SpanCostDetail.is_prompt,
88
+ func.sum(models.SpanCostDetail.cost).label("cost"),
89
+ func.sum(models.SpanCostDetail.tokens).label("tokens"),
90
+ )
91
+ .select_from(models.SpanCostDetail)
92
+ .join(models.SpanCost, models.SpanCostDetail.span_cost_id == models.SpanCost.id)
93
+ .join(models.Trace, models.SpanCost.trace_rowid == models.Trace.id)
94
+ .join(models.ExperimentRun, models.ExperimentRun.trace_id == models.Trace.trace_id)
95
+ .where(models.ExperimentRun.experiment_id == experiment_id)
96
+ .where(models.ExperimentRun.dataset_example_id == example_id)
97
+ .group_by(models.SpanCostDetail.token_type, models.SpanCostDetail.is_prompt)
98
+ )
99
+
100
+ async with info.context.db() as session:
101
+ data = await session.stream(stmt)
102
+ return [
103
+ SpanCostDetailSummaryEntry(
104
+ token_type=token_type,
105
+ is_prompt=is_prompt,
106
+ value=CostBreakdown(tokens=tokens, cost=cost),
107
+ )
108
+ async for token_type, is_prompt, cost, tokens in data
109
+ ]
110
+
111
+ @strawberry.field
112
+ async def annotation_summaries(
113
+ self,
114
+ info: Info[Context, None],
115
+ ) -> list[ExperimentRepeatedRunGroupAnnotationSummary]:
116
+ loader = info.context.data_loaders.experiment_repeated_run_group_annotation_summaries
117
+ summaries = await loader.load((self.experiment_rowid, self.dataset_example_rowid))
118
+ return [
119
+ ExperimentRepeatedRunGroupAnnotationSummary(
120
+ annotation_name=summary.annotation_name,
121
+ mean_score=summary.mean_score,
122
+ )
123
+ for summary in summaries
124
+ ]
125
+
126
+
127
+ _EXPERIMENT_REPEATED_RUN_GROUP_NODE_ID_PATTERN = re.compile(
128
+ r"ExperimentRepeatedRunGroup:experiment_id=(\d+):dataset_example_id=(\d+)"
129
+ )
130
+
131
+
132
+ def parse_experiment_repeated_run_group_node_id(
133
+ node_id: str,
134
+ ) -> tuple[ExperimentRowId, DatasetExampleRowId]:
135
+ decoded_node_id = _base64_decode(node_id)
136
+ match = re.match(_EXPERIMENT_REPEATED_RUN_GROUP_NODE_ID_PATTERN, decoded_node_id)
137
+ if not match:
138
+ raise ValueError(f"Invalid node ID format: {node_id}")
139
+
140
+ experiment_id = int(match.group(1))
141
+ dataset_example_id = int(match.group(2))
142
+ return experiment_id, dataset_example_id
143
+
144
+
145
+ def _base64_decode(string: str) -> str:
146
+ return b64decode(string.encode()).decode()
@@ -0,0 +1,9 @@
1
+ from typing import Optional
2
+
3
+ import strawberry
4
+
5
+
6
+ @strawberry.type
7
+ class ExperimentRepeatedRunGroupAnnotationSummary:
8
+ annotation_name: str
9
+ mean_score: Optional[float]
@@ -3,7 +3,6 @@ from typing import TYPE_CHECKING, Annotated, Optional
3
3
 
4
4
  import strawberry
5
5
  from sqlalchemy import func, select
6
- from sqlalchemy.orm import load_only
7
6
  from sqlalchemy.sql.functions import coalesce
8
7
  from strawberry import UNSET
9
8
  from strawberry.relay import Connection, GlobalID, Node, NodeID
@@ -34,12 +33,17 @@ if TYPE_CHECKING:
34
33
  class ExperimentRun(Node):
35
34
  id_attr: NodeID[int]
36
35
  experiment_id: GlobalID
36
+ repetition_number: int
37
37
  trace_id: Optional[str]
38
38
  output: Optional[JSON]
39
39
  start_time: datetime
40
40
  end_time: datetime
41
41
  error: Optional[str]
42
42
 
43
+ @strawberry.field
44
+ def latency_ms(self) -> float:
45
+ return (self.end_time - self.start_time).total_seconds() * 1000
46
+
43
47
  @strawberry.field
44
48
  async def annotations(
45
49
  self,
@@ -78,24 +82,12 @@ class ExperimentRun(Node):
78
82
  ]: # use lazy types to avoid circular import: https://strawberry.rocks/docs/types/lazy
79
83
  from phoenix.server.api.types.DatasetExample import DatasetExample
80
84
 
81
- async with info.context.db() as session:
82
- assert (
83
- result := await session.execute(
84
- select(models.DatasetExample, models.Experiment.dataset_version_id)
85
- .select_from(models.ExperimentRun)
86
- .join(
87
- models.DatasetExample,
88
- models.DatasetExample.id == models.ExperimentRun.dataset_example_id,
89
- )
90
- .join(
91
- models.Experiment,
92
- models.Experiment.id == models.ExperimentRun.experiment_id,
93
- )
94
- .where(models.ExperimentRun.id == self.id_attr)
95
- .options(load_only(models.DatasetExample.id, models.DatasetExample.created_at))
96
- )
97
- ) is not None
98
- example, version_id = result.first()
85
+ (
86
+ example,
87
+ version_id,
88
+ ) = await info.context.data_loaders.dataset_examples_and_versions_by_experiment_run.load(
89
+ self.id_attr
90
+ )
99
91
  return DatasetExample(
100
92
  id_attr=example.id,
101
93
  created_at=example.created_at,
@@ -165,6 +157,7 @@ def to_gql_experiment_run(run: models.ExperimentRun) -> ExperimentRun:
165
157
  return ExperimentRun(
166
158
  id_attr=run.id,
167
159
  experiment_id=GlobalID(Experiment.__name__, str(run.experiment_id)),
160
+ repetition_number=run.repetition_number,
168
161
  trace_id=run.trace.trace_id if run.trace else None,
169
162
  output=run.output.get("task_output"),
170
163
  start_time=run.start_time,
@@ -19,6 +19,7 @@ from phoenix.server.api.types.pagination import (
19
19
  connection_from_list,
20
20
  )
21
21
 
22
+ from .PromptLabel import PromptLabel, to_gql_prompt_label
22
23
  from .PromptVersion import (
23
24
  PromptVersion,
24
25
  to_gql_prompt_version,
@@ -116,6 +117,16 @@ class Prompt(Node):
116
117
  raise NotFound(f"Source prompt not found: {self.source_prompt_id}")
117
118
  return to_gql_prompt_from_orm(source_prompt)
118
119
 
120
+ @strawberry.field
121
+ async def labels(self, info: Info[Context, None]) -> list["PromptLabel"]:
122
+ async with info.context.db() as session:
123
+ labels = await session.scalars(
124
+ select(models.PromptLabel)
125
+ .join(models.PromptPromptLabel)
126
+ .where(models.PromptPromptLabel.prompt_id == self.id_attr)
127
+ )
128
+ return [to_gql_prompt_label(label) for label in labels]
129
+
119
130
 
120
131
  def to_gql_prompt_from_orm(orm_model: "models.Prompt") -> Prompt:
121
132
  if not orm_model.source_prompt_id:
@@ -1,14 +1,10 @@
1
1
  from typing import Optional
2
2
 
3
3
  import strawberry
4
- from sqlalchemy import select
5
4
  from strawberry.relay import Node, NodeID
6
- from strawberry.types import Info
7
5
 
8
6
  from phoenix.db import models
9
- from phoenix.server.api.context import Context
10
7
  from phoenix.server.api.types.Identifier import Identifier
11
- from phoenix.server.api.types.Prompt import Prompt, to_gql_prompt_from_orm
12
8
 
13
9
 
14
10
  @strawberry.type
@@ -16,21 +12,7 @@ class PromptLabel(Node):
16
12
  id_attr: NodeID[int]
17
13
  name: Identifier
18
14
  description: Optional[str] = None
19
-
20
- @strawberry.field
21
- async def prompts(self, info: Info[Context, None]) -> list[Prompt]:
22
- async with info.context.db() as session:
23
- statement = (
24
- select(models.Prompt)
25
- .join(
26
- models.PromptPromptLabel, models.Prompt.id == models.PromptPromptLabel.prompt_id
27
- )
28
- .where(models.PromptPromptLabel.prompt_label_id == self.id_attr)
29
- )
30
- return [
31
- to_gql_prompt_from_orm(prompt_orm)
32
- async for prompt_orm in await session.stream_scalars(statement)
33
- ]
15
+ color: str
34
16
 
35
17
 
36
18
  def to_gql_prompt_label(label_orm: models.PromptLabel) -> PromptLabel:
@@ -38,4 +20,5 @@ def to_gql_prompt_label(label_orm: models.PromptLabel) -> PromptLabel:
38
20
  id_attr=label_orm.id,
39
21
  name=Identifier(label_orm.name),
40
22
  description=label_orm.description,
23
+ color=label_orm.color,
41
24
  )
@@ -1,5 +1,15 @@
1
+ import re
2
+ from base64 import b64decode
3
+
1
4
  from strawberry.relay import GlobalID
2
5
 
6
+ _GLOBAL_ID_PATTERN = re.compile(r"[a-zA-Z]+:[0-9]+")
7
+
8
+
9
+ def is_global_id(node_id: str) -> bool:
10
+ decoded_node_id = b64decode(node_id).decode()
11
+ return _GLOBAL_ID_PATTERN.match(decoded_node_id) is not None
12
+
3
13
 
4
14
  def from_global_id(global_id: GlobalID) -> tuple[str, int]:
5
15
  """
phoenix/server/app.py CHANGED
@@ -81,15 +81,20 @@ from phoenix.server.api.context import Context, DataLoaders
81
81
  from phoenix.server.api.dataloaders import (
82
82
  AnnotationConfigsByProjectDataLoader,
83
83
  AnnotationSummaryDataLoader,
84
+ AverageExperimentRepeatedRunGroupLatencyDataLoader,
84
85
  AverageExperimentRunLatencyDataLoader,
85
86
  CacheForDataLoaders,
86
87
  DatasetExampleRevisionsDataLoader,
88
+ DatasetExamplesAndVersionsByExperimentRunDataLoader,
87
89
  DatasetExampleSpansDataLoader,
88
90
  DocumentEvaluationsDataLoader,
89
91
  DocumentEvaluationSummaryDataLoader,
90
92
  DocumentRetrievalMetricsDataLoader,
91
93
  ExperimentAnnotationSummaryDataLoader,
92
94
  ExperimentErrorRatesDataLoader,
95
+ ExperimentRepeatedRunGroupAnnotationSummariesDataLoader,
96
+ ExperimentRepeatedRunGroupsDataLoader,
97
+ ExperimentRepetitionCountsDataLoader,
93
98
  ExperimentRunAnnotations,
94
99
  ExperimentRunCountsDataLoader,
95
100
  ExperimentSequenceNumberDataLoader,
@@ -116,6 +121,7 @@ from phoenix.server.api.dataloaders import (
116
121
  SpanCostDetailSummaryEntriesBySpanDataLoader,
117
122
  SpanCostDetailSummaryEntriesByTraceDataLoader,
118
123
  SpanCostSummaryByExperimentDataLoader,
124
+ SpanCostSummaryByExperimentRepeatedRunGroupDataLoader,
119
125
  SpanCostSummaryByExperimentRunDataLoader,
120
126
  SpanCostSummaryByGenerativeModelDataLoader,
121
127
  SpanCostSummaryByProjectDataLoader,
@@ -663,9 +669,15 @@ def create_graphql_router(
663
669
  event_queue=event_queue,
664
670
  data_loaders=DataLoaders(
665
671
  annotation_configs_by_project=AnnotationConfigsByProjectDataLoader(db),
672
+ average_experiment_repeated_run_group_latency=AverageExperimentRepeatedRunGroupLatencyDataLoader(
673
+ db
674
+ ),
666
675
  average_experiment_run_latency=AverageExperimentRunLatencyDataLoader(db),
667
676
  dataset_example_revisions=DatasetExampleRevisionsDataLoader(db),
668
677
  dataset_example_spans=DatasetExampleSpansDataLoader(db),
678
+ dataset_examples_and_versions_by_experiment_run=DatasetExamplesAndVersionsByExperimentRunDataLoader(
679
+ db
680
+ ),
669
681
  document_evaluation_summaries=DocumentEvaluationSummaryDataLoader(
670
682
  db,
671
683
  cache_map=(
@@ -684,6 +696,11 @@ def create_graphql_router(
684
696
  ),
685
697
  experiment_annotation_summaries=ExperimentAnnotationSummaryDataLoader(db),
686
698
  experiment_error_rates=ExperimentErrorRatesDataLoader(db),
699
+ experiment_repeated_run_group_annotation_summaries=ExperimentRepeatedRunGroupAnnotationSummariesDataLoader(
700
+ db
701
+ ),
702
+ experiment_repeated_run_groups=ExperimentRepeatedRunGroupsDataLoader(db),
703
+ experiment_repetition_counts=ExperimentRepetitionCountsDataLoader(db),
687
704
  experiment_run_annotations=ExperimentRunAnnotations(db),
688
705
  experiment_run_counts=ExperimentRunCountsDataLoader(db),
689
706
  experiment_sequence_number=ExperimentSequenceNumberDataLoader(db),
@@ -740,6 +757,11 @@ def create_graphql_router(
740
757
  span_cost_details_by_span_cost=SpanCostDetailsBySpanCostDataLoader(db),
741
758
  span_cost_detail_fields=TableFieldsDataLoader(db, models.SpanCostDetail),
742
759
  span_cost_fields=TableFieldsDataLoader(db, models.SpanCost),
760
+ span_cost_summary_by_experiment=SpanCostSummaryByExperimentDataLoader(db),
761
+ span_cost_summary_by_experiment_repeated_run_group=SpanCostSummaryByExperimentRepeatedRunGroupDataLoader(
762
+ db
763
+ ),
764
+ span_cost_summary_by_experiment_run=SpanCostSummaryByExperimentRunDataLoader(db),
743
765
  span_cost_summary_by_generative_model=SpanCostSummaryByGenerativeModelDataLoader(
744
766
  db
745
767
  ),
@@ -768,8 +790,6 @@ def create_graphql_router(
768
790
  project_by_name=ProjectByNameDataLoader(db),
769
791
  users=UsersDataLoader(db),
770
792
  user_roles=UserRolesDataLoader(db),
771
- span_cost_summary_by_experiment=SpanCostSummaryByExperimentDataLoader(db),
772
- span_cost_summary_by_experiment_run=SpanCostSummaryByExperimentRunDataLoader(db),
773
793
  ),
774
794
  cache_for_dataloaders=cache_for_dataloaders,
775
795
  read_only=read_only,
@@ -698,7 +698,7 @@
698
698
  "token_type": "input"
699
699
  },
700
700
  {
701
- "base_rate": 2.5e-6,
701
+ "base_rate": 0.00003,
702
702
  "is_prompt": false,
703
703
  "token_type": "output"
704
704
  },
@@ -1,73 +1,73 @@
1
1
  {
2
- "_components-Cs9c4Nxp.js": {
3
- "file": "assets/components-Cs9c4Nxp.js",
2
+ "_components-YTHUASXI.js": {
3
+ "file": "assets/components-YTHUASXI.js",
4
4
  "name": "components",
5
5
  "imports": [
6
- "_vendor-RdRDaQiR.js",
7
- "_pages-Cbj9SjBx.js",
8
- "_vendor-arizeai-DsYDNOqt.js",
9
- "_vendor-codemirror-BzJDUbEx.js",
6
+ "_vendor-CRRxHwSp.js",
7
+ "_pages-4Qu8GNlt.js",
8
+ "_vendor-arizeai-CUN6lRd9.js",
9
+ "_vendor-codemirror-sJXwoqrE.js",
10
10
  "_vendor-three-BLWp5bic.js"
11
11
  ]
12
12
  },
13
- "_pages-Cbj9SjBx.js": {
14
- "file": "assets/pages-Cbj9SjBx.js",
13
+ "_pages-4Qu8GNlt.js": {
14
+ "file": "assets/pages-4Qu8GNlt.js",
15
15
  "name": "pages",
16
16
  "imports": [
17
- "_vendor-RdRDaQiR.js",
18
- "_vendor-arizeai-DsYDNOqt.js",
19
- "_components-Cs9c4Nxp.js",
20
- "_vendor-codemirror-BzJDUbEx.js",
21
- "_vendor-recharts-BTHn5Y2R.js"
17
+ "_vendor-CRRxHwSp.js",
18
+ "_vendor-arizeai-CUN6lRd9.js",
19
+ "_components-YTHUASXI.js",
20
+ "_vendor-codemirror-sJXwoqrE.js",
21
+ "_vendor-recharts-BT_PeGhc.js"
22
22
  ]
23
23
  },
24
- "_vendor-CqDb5u4o.css": {
25
- "file": "assets/vendor-CqDb5u4o.css",
26
- "src": "_vendor-CqDb5u4o.css"
24
+ "_vendor-BGzfc4EU.css": {
25
+ "file": "assets/vendor-BGzfc4EU.css",
26
+ "src": "_vendor-BGzfc4EU.css"
27
27
  },
28
- "_vendor-RdRDaQiR.js": {
29
- "file": "assets/vendor-RdRDaQiR.js",
28
+ "_vendor-CRRxHwSp.js": {
29
+ "file": "assets/vendor-CRRxHwSp.js",
30
30
  "name": "vendor",
31
31
  "imports": [
32
32
  "_vendor-three-BLWp5bic.js"
33
33
  ],
34
34
  "css": [
35
- "assets/vendor-CqDb5u4o.css"
35
+ "assets/vendor-BGzfc4EU.css"
36
36
  ]
37
37
  },
38
- "_vendor-arizeai-DsYDNOqt.js": {
39
- "file": "assets/vendor-arizeai-DsYDNOqt.js",
38
+ "_vendor-arizeai-CUN6lRd9.js": {
39
+ "file": "assets/vendor-arizeai-CUN6lRd9.js",
40
40
  "name": "vendor-arizeai",
41
41
  "imports": [
42
- "_vendor-RdRDaQiR.js"
42
+ "_vendor-CRRxHwSp.js"
43
43
  ]
44
44
  },
45
- "_vendor-codemirror-BzJDUbEx.js": {
46
- "file": "assets/vendor-codemirror-BzJDUbEx.js",
45
+ "_vendor-codemirror-sJXwoqrE.js": {
46
+ "file": "assets/vendor-codemirror-sJXwoqrE.js",
47
47
  "name": "vendor-codemirror",
48
48
  "imports": [
49
- "_vendor-RdRDaQiR.js",
50
- "_vendor-shiki-BAcocHFl.js"
49
+ "_vendor-CRRxHwSp.js",
50
+ "_vendor-shiki-1F3op0QC.js"
51
51
  ],
52
52
  "dynamicImports": [
53
- "_vendor-shiki-BAcocHFl.js",
54
- "_vendor-shiki-BAcocHFl.js",
55
- "_vendor-shiki-BAcocHFl.js"
53
+ "_vendor-shiki-1F3op0QC.js",
54
+ "_vendor-shiki-1F3op0QC.js",
55
+ "_vendor-shiki-1F3op0QC.js"
56
56
  ]
57
57
  },
58
- "_vendor-recharts-BTHn5Y2R.js": {
59
- "file": "assets/vendor-recharts-BTHn5Y2R.js",
58
+ "_vendor-recharts-BT_PeGhc.js": {
59
+ "file": "assets/vendor-recharts-BT_PeGhc.js",
60
60
  "name": "vendor-recharts",
61
61
  "imports": [
62
- "_vendor-RdRDaQiR.js"
62
+ "_vendor-CRRxHwSp.js"
63
63
  ]
64
64
  },
65
- "_vendor-shiki-BAcocHFl.js": {
66
- "file": "assets/vendor-shiki-BAcocHFl.js",
65
+ "_vendor-shiki-1F3op0QC.js": {
66
+ "file": "assets/vendor-shiki-1F3op0QC.js",
67
67
  "name": "vendor-shiki",
68
68
  "isDynamicEntry": true,
69
69
  "imports": [
70
- "_vendor-RdRDaQiR.js"
70
+ "_vendor-CRRxHwSp.js"
71
71
  ]
72
72
  },
73
73
  "_vendor-three-BLWp5bic.js": {
@@ -75,19 +75,19 @@
75
75
  "name": "vendor-three"
76
76
  },
77
77
  "index.tsx": {
78
- "file": "assets/index-D1FDMBMV.js",
78
+ "file": "assets/index-CugQp26L.js",
79
79
  "name": "index",
80
80
  "src": "index.tsx",
81
81
  "isEntry": true,
82
82
  "imports": [
83
- "_vendor-RdRDaQiR.js",
84
- "_vendor-arizeai-DsYDNOqt.js",
85
- "_pages-Cbj9SjBx.js",
86
- "_components-Cs9c4Nxp.js",
83
+ "_vendor-CRRxHwSp.js",
84
+ "_vendor-arizeai-CUN6lRd9.js",
85
+ "_pages-4Qu8GNlt.js",
86
+ "_components-YTHUASXI.js",
87
87
  "_vendor-three-BLWp5bic.js",
88
- "_vendor-codemirror-BzJDUbEx.js",
89
- "_vendor-shiki-BAcocHFl.js",
90
- "_vendor-recharts-BTHn5Y2R.js"
88
+ "_vendor-codemirror-sJXwoqrE.js",
89
+ "_vendor-shiki-1F3op0QC.js",
90
+ "_vendor-recharts-BT_PeGhc.js"
91
91
  ]
92
92
  }
93
93
  }