1- import { Link , type RouteHandle } from "react-router" ;
1+ import { Link , type RouteHandle , Await } from "react-router" ;
2+ import * as React from "react" ;
23import { Card } from "~/components/ui/card" ;
34import { PageLayout } from "~/components/layout/PageLayout" ;
45import {
@@ -21,10 +22,9 @@ import {
2122 countInferencesByFunction ,
2223 countEpisodes ,
2324} from "~/utils/clickhouse/inference.server" ;
24- import { getAllFunctionConfigs } from "~/utils/config/index.server" ;
25+ import { getConfig , getAllFunctionConfigs } from "~/utils/config/index.server" ;
2526import { getDatasetCounts } from "~/utils/clickhouse/datasets.server" ;
2627import { countTotalEvaluationRuns } from "~/utils/clickhouse/evaluations.server" ;
27- import { useConfig } from "~/context/config" ;
2828import type { Route } from "./+types/index" ;
2929import {
3030 countDynamicEvaluationProjects ,
@@ -39,7 +39,7 @@ interface DirectoryCardProps {
3939 source : string ;
4040 icon : React . ComponentType < { className ?: string ; size ?: number } > ;
4141 title : string ;
42- description : string ;
42+ description : string | Promise < string > ;
4343}
4444
4545function DirectoryCard ( {
@@ -62,7 +62,19 @@ function DirectoryCard({
6262 { title }
6363 </ h3 >
6464 < p className = "text-fg-secondary overflow-hidden text-xs text-ellipsis whitespace-nowrap" >
65- { description }
65+ { typeof description === "string" ? (
66+ description
67+ ) : (
68+ < React . Suspense
69+ fallback = {
70+ < span className = "bg-bg-tertiary inline-block h-3 w-16 animate-pulse rounded" > </ span >
71+ }
72+ >
73+ < Await resolve = { description } >
74+ { ( resolvedDescription ) => resolvedDescription }
75+ </ Await >
76+ </ React . Suspense >
77+ ) }
6678 </ p >
6779 </ div >
6880 </ Card >
@@ -93,55 +105,88 @@ function FooterLink({ source, icon: Icon, children }: FooterLinkProps) {
93105}
94106
95107export async function loader ( ) {
96- const [
97- countsInfo ,
98- numEpisodes ,
99- datasetCounts ,
100- numEvaluationRuns ,
101- numDynamicEvaluationRuns ,
102- numDynamicEvaluationRunProjects ,
103- functionConfigs ,
104- ] = await Promise . all ( [
105- countInferencesByFunction ( ) ,
106- countEpisodes ( ) ,
107- getDatasetCounts ( { } ) ,
108- countTotalEvaluationRuns ( ) ,
109- countDynamicEvaluationRuns ( ) ,
110- countDynamicEvaluationProjects ( ) ,
111- getAllFunctionConfigs ( ) ,
112- ] ) ;
113- const totalInferences = countsInfo . reduce ( ( acc , curr ) => acc + curr . count , 0 ) ;
114- const numFunctions = Object . keys ( functionConfigs ) . length ;
115- const numVariants = Object . values ( functionConfigs ) . reduce ( ( acc , config ) => {
116- return acc + ( config ? Object . keys ( config . variants || { } ) . length : 0 ) ;
117- } , 0 ) ;
118- const numDatasets = datasetCounts . length ;
108+ // Create the promises
109+ const countsInfoPromise = countInferencesByFunction ( ) ;
110+ const numEpisodesPromise = countEpisodes ( ) ;
111+ const datasetCountsPromise = getDatasetCounts ( { } ) ;
112+ const numEvaluationRunsPromise = countTotalEvaluationRuns ( ) ;
113+ const numDynamicEvaluationRunsPromise = countDynamicEvaluationRuns ( ) ;
114+ const numDynamicEvaluationRunProjectsPromise =
115+ countDynamicEvaluationProjects ( ) ;
116+ const configPromise = getConfig ( ) ;
117+ const functionConfigsPromise = getAllFunctionConfigs ( ) ;
118+
119+ // Create derived promises - these will be stable references
120+ const totalInferencesDesc = countsInfoPromise . then ( ( countsInfo ) => {
121+ const total = countsInfo . reduce ( ( acc , curr ) => acc + curr . count , 0 ) ;
122+ return `${ total . toLocaleString ( ) } inferences` ;
123+ } ) ;
124+
125+ const numFunctionsDesc = functionConfigsPromise . then ( ( functionConfigs ) => {
126+ const numFunctions = Object . keys ( functionConfigs ) . length ;
127+ return `${ numFunctions } functions` ;
128+ } ) ;
129+
130+ const numVariantsDesc = functionConfigsPromise . then ( ( functionConfigs ) => {
131+ const numVariants = Object . values ( functionConfigs ) . reduce (
132+ ( acc , funcConfig ) => {
133+ return (
134+ acc + ( funcConfig ? Object . keys ( funcConfig . variants || { } ) . length : 0 )
135+ ) ;
136+ } ,
137+ 0 ,
138+ ) ;
139+ return `${ numVariants } variants` ;
140+ } ) ;
141+
142+ const numEpisodesDesc = numEpisodesPromise . then (
143+ ( numEpisodes ) => `${ numEpisodes . toLocaleString ( ) } episodes` ,
144+ ) ;
145+
146+ const numDatasetsDesc = datasetCountsPromise . then (
147+ ( datasetCounts ) => `${ datasetCounts . length } datasets` ,
148+ ) ;
149+
150+ const numEvaluationRunsDesc = numEvaluationRunsPromise . then (
151+ ( runs ) => `evaluations, ${ runs } runs` ,
152+ ) ;
153+
154+ // We need to create a special promise for the static evaluations that includes the config count
155+ const staticEvaluationsDesc = Promise . all ( [
156+ configPromise ,
157+ numEvaluationRunsPromise ,
158+ ] ) . then ( ( [ config , runs ] ) => {
159+ const numEvaluations = Object . keys ( config . evaluations || { } ) . length ;
160+ return `${ numEvaluations } evaluations, ${ runs } runs` ;
161+ } ) ;
162+
163+ const dynamicEvaluationsDesc = Promise . all ( [
164+ numDynamicEvaluationRunProjectsPromise ,
165+ numDynamicEvaluationRunsPromise ,
166+ ] ) . then ( ( [ projects , runs ] ) => `${ projects } projects, ${ runs } runs` ) ;
119167
120168 return {
121- totalInferences ,
122- numFunctions ,
123- numVariants ,
124- numEpisodes ,
125- numDatasets ,
126- numEvaluationRuns ,
127- numDynamicEvaluationRuns ,
128- numDynamicEvaluationRunProjects ,
169+ totalInferencesDesc ,
170+ numFunctionsDesc ,
171+ numVariantsDesc ,
172+ numEpisodesDesc ,
173+ numDatasetsDesc ,
174+ numEvaluationRunsDesc ,
175+ staticEvaluationsDesc ,
176+ dynamicEvaluationsDesc ,
129177 } ;
130178}
131179
132180export default function Home ( { loaderData } : Route . ComponentProps ) {
133181 const {
134- totalInferences,
135- numFunctions,
136- numVariants,
137- numEpisodes,
138- numDatasets,
139- numEvaluationRuns,
140- numDynamicEvaluationRuns,
141- numDynamicEvaluationRunProjects,
182+ totalInferencesDesc,
183+ numFunctionsDesc,
184+ numVariantsDesc,
185+ numEpisodesDesc,
186+ numDatasetsDesc,
187+ staticEvaluationsDesc,
188+ dynamicEvaluationsDesc,
142189 } = loaderData ;
143- const config = useConfig ( ) ;
144- const numEvaluations = Object . keys ( config . evaluations ) . length ;
145190
146191 return (
147192 < PageLayout >
@@ -157,19 +202,19 @@ export default function Home({ loaderData }: Route.ComponentProps) {
157202 source = "/observability/inferences"
158203 icon = { Inferences }
159204 title = "Inferences"
160- description = { ` ${ totalInferences . toLocaleString ( ) } inferences` }
205+ description = { totalInferencesDesc }
161206 />
162207 < DirectoryCard
163208 source = "/observability/episodes"
164209 icon = { Episodes }
165210 title = "Episodes"
166- description = { ` ${ numEpisodes . toLocaleString ( ) } episodes` }
211+ description = { numEpisodesDesc }
167212 />
168213 < DirectoryCard
169214 source = "/observability/functions"
170215 icon = { Functions }
171216 title = "Functions"
172- description = { ` ${ numFunctions } functions` }
217+ description = { numFunctionsDesc }
173218 />
174219 </ div >
175220 </ div >
@@ -183,7 +228,7 @@ export default function Home({ loaderData }: Route.ComponentProps) {
183228 source = "/optimization/supervised-fine-tuning"
184229 icon = { SupervisedFineTuning }
185230 title = "Supervised Fine-tuning"
186- description = { ` ${ numFunctions } functions` }
231+ description = { numFunctionsDesc }
187232 />
188233 </ div >
189234 </ div >
@@ -195,25 +240,25 @@ export default function Home({ loaderData }: Route.ComponentProps) {
195240 source = "/playground"
196241 icon = { Playground }
197242 title = "Playground"
198- description = { ` ${ numVariants } variants` }
243+ description = { numVariantsDesc }
199244 />
200245 < DirectoryCard
201246 source = "/datasets"
202247 icon = { Dataset }
203248 title = "Datasets"
204- description = { ` ${ numDatasets } datasets` }
249+ description = { numDatasetsDesc }
205250 />
206251 < DirectoryCard
207252 source = "/evaluations"
208253 icon = { GridCheck }
209254 title = "Static Evaluations"
210- description = { ` ${ numEvaluations } evaluations, ${ numEvaluationRuns } runs` }
255+ description = { staticEvaluationsDesc }
211256 />
212257 < DirectoryCard
213258 source = "/dynamic_evaluations"
214259 icon = { SequenceChecks }
215260 title = "Dynamic Evaluations"
216- description = { ` ${ numDynamicEvaluationRunProjects } projects, ${ numDynamicEvaluationRuns } runs` }
261+ description = { dynamicEvaluationsDesc }
217262 />
218263 </ div >
219264 </ div >
0 commit comments