@@ -2,114 +2,120 @@ import { redirect } from '@sveltejs/kit';
22import type { PageServerLoad } from './$types' ;
33import { auth } from '$lib/auth' ;
44import {
5- getModelPerformanceStatsByUser ,
6- calculateAllModelPerformanceStats ,
5+ getModelPerformanceStatsByUser ,
6+ calculateAllModelPerformanceStats ,
77} from '$lib/db/queries/model-performance' ;
88
99export const load : PageServerLoad = async ( { request } ) => {
10- const session = await auth . api . getSession ( { headers : request . headers } ) ;
10+ const session = await auth . api . getSession ( { headers : request . headers } ) ;
1111
12- if ( ! session ?. user ?. id ) {
13- throw redirect ( 302 , '/' ) ;
14- }
12+ if ( ! session ?. user ?. id ) {
13+ throw redirect ( 302 , '/' ) ;
14+ }
1515
16- const userId = session . user . id ;
16+ const userId = session . user . id ;
1717
18- try {
19- console . log ( `[analytics] Loading analytics for user ${ userId } ` ) ;
18+ try {
19+ console . log ( `[analytics] Loading analytics for user ${ userId } ` ) ;
2020
21- // Always recalculate stats to ensure they're up-to-date
22- const stats = await calculateAllModelPerformanceStats ( userId ) ;
23- console . log ( `[analytics] Calculated stats for ${ stats . length } models` ) ;
21+ // Always recalculate stats to ensure they're up-to-date
22+ const stats = await calculateAllModelPerformanceStats ( userId ) ;
23+ console . log ( `[analytics] Calculated stats for ${ stats . length } models` ) ;
2424
25- // Calculate additional insights
26- const totalMessages = stats . reduce ( ( sum , s ) => sum + s . totalMessages , 0 ) ;
27- const totalCost = stats . reduce ( ( sum , s ) => sum + s . totalCost , 0 ) ;
28- const avgRating =
29- stats . filter ( ( s ) => s . avgRating !== null ) . length > 0
30- ? stats . reduce ( ( sum , s ) => sum + ( s . avgRating ?? 0 ) , 0 ) /
31- stats . filter ( ( s ) => s . avgRating !== null ) . length
32- : null ;
25+ // Calculate additional insights
26+ const totalMessages = stats . reduce ( ( sum , s ) => sum + s . totalMessages , 0 ) ;
27+ const totalCost = stats . reduce ( ( sum , s ) => {
28+ const cost = s . totalCost ;
29+ if ( cost === null || cost === undefined || isNaN ( cost ) ) {
30+ return sum ;
31+ }
32+ return sum + cost ;
33+ } , 0 ) ;
34+ const avgRating =
35+ stats . filter ( ( s ) => s . avgRating !== null ) . length > 0
36+ ? stats . reduce ( ( sum , s ) => sum + ( s . avgRating ?? 0 ) , 0 ) /
37+ stats . filter ( ( s ) => s . avgRating !== null ) . length
38+ : null ;
3339
34- // Find most used model
35- const mostUsedModel = stats . length > 0
36- ? stats . reduce (
37- ( prev , current ) => ( current . totalMessages > prev . totalMessages ? current : prev ) ,
38- stats [ 0 ] !
39- )
40- : null ;
40+ // Find most used model
41+ const mostUsedModel =
42+ stats . length > 0
43+ ? stats . reduce (
44+ ( prev , current ) => ( current . totalMessages > prev . totalMessages ? current : prev ) ,
45+ stats [ 0 ] !
46+ )
47+ : null ;
4148
42- // Find best rated model (with at least 5 messages)
43- const qualifiedModels = stats . filter ( ( s ) => s . totalMessages >= 5 && s . avgRating !== null ) ;
44- const bestRatedModel =
45- qualifiedModels . length > 0
46- ? qualifiedModels . reduce ( ( prev , current ) =>
47- ( current . avgRating ?? 0 ) > ( prev . avgRating ?? 0 ) ? current : prev
48- )
49- : null ;
49+ // Find best rated model (with at least 5 messages)
50+ const qualifiedModels = stats . filter ( ( s ) => s . totalMessages >= 5 && s . avgRating !== null ) ;
51+ const bestRatedModel =
52+ qualifiedModels . length > 0
53+ ? qualifiedModels . reduce ( ( prev , current ) =>
54+ ( current . avgRating ?? 0 ) > ( prev . avgRating ?? 0 ) ? current : prev
55+ )
56+ : null ;
5057
51- // Find most cost-effective model (lowest cost per message with at least 5 messages)
52- const modelsWithCost = stats . filter ( ( s ) => s . totalMessages >= 5 && s . totalCost > 0 ) ;
53- const mostCostEffective =
54- modelsWithCost . length > 0
55- ? modelsWithCost . reduce ( ( prev , current ) => {
56- const prevCostPerMsg = prev . totalCost / prev . totalMessages ;
57- const currentCostPerMsg = current . totalCost / current . totalMessages ;
58- return currentCostPerMsg < prevCostPerMsg ? current : prev ;
59- } )
60- : null ;
58+ // Find most cost-effective model (lowest cost per message with at least 5 messages)
59+ const modelsWithCost = stats . filter ( ( s ) => s . totalMessages >= 5 && s . totalCost > 0 ) ;
60+ const mostCostEffective =
61+ modelsWithCost . length > 0
62+ ? modelsWithCost . reduce ( ( prev , current ) => {
63+ const prevCostPerMsg = prev . totalCost / prev . totalMessages ;
64+ const currentCostPerMsg = current . totalCost / current . totalMessages ;
65+ return currentCostPerMsg < prevCostPerMsg ? current : prev ;
66+ } )
67+ : null ;
6168
62- // Find fastest model by tokens/sec (requires avgTokens and avgResponseTime with at least 5 messages)
63- const modelsWithSpeed = stats . filter (
64- ( s ) =>
65- s . totalMessages >= 5 &&
66- s . avgTokens !== null &&
67- s . avgTokens !== undefined &&
68- s . avgResponseTime !== null &&
69- s . avgResponseTime !== undefined &&
70- s . avgResponseTime > 0
71- ) ;
69+ // Find fastest model by tokens/sec (requires avgTokens and avgResponseTime with at least 5 messages)
70+ const modelsWithSpeed = stats . filter (
71+ ( s ) =>
72+ s . totalMessages >= 5 &&
73+ s . avgTokens !== null &&
74+ s . avgTokens !== undefined &&
75+ s . avgResponseTime !== null &&
76+ s . avgResponseTime !== undefined &&
77+ s . avgResponseTime > 0
78+ ) ;
7279
73- const fastestModel =
74- modelsWithSpeed . length > 0
75- ? modelsWithSpeed . reduce ( ( prev , current ) => {
76- const prevSpeed =
77- ( prev . avgTokens ?? 0 ) /
78- ( ( ( prev . avgResponseTime ?? 0 ) / 1000 ) || 1 ) ; // tokens per second
79- const currentSpeed =
80- ( current . avgTokens ?? 0 ) /
81- ( ( ( current . avgResponseTime ?? 0 ) / 1000 ) || 1 ) ;
82- return currentSpeed > prevSpeed ? current : prev ;
83- } )
84- : null ;
80+ const fastestModel =
81+ modelsWithSpeed . length > 0
82+ ? modelsWithSpeed . reduce ( ( prev , current ) => {
83+ const prevSpeed = ( prev . avgTokens ?? 0 ) / ( ( prev . avgResponseTime ?? 0 ) / 1000 || 1 ) ; // tokens per second
84+ const currentSpeed =
85+ ( current . avgTokens ?? 0 ) / ( ( current . avgResponseTime ?? 0 ) / 1000 || 1 ) ;
86+ return currentSpeed > prevSpeed ? current : prev ;
87+ } )
88+ : null ;
8589
86- console . log ( `[analytics] Generated insights: ${ totalMessages } messages, $${ totalCost . toFixed ( 2 ) } cost` ) ;
90+ console . log (
91+ `[analytics] Generated insights: ${ totalMessages } messages, $${ totalCost . toFixed ( 2 ) } cost`
92+ ) ;
8793
88- return {
89- stats,
90- insights : {
91- totalMessages,
92- totalCost,
93- avgRating,
94- mostUsedModel,
95- bestRatedModel,
96- mostCostEffective,
97- fastestModel,
98- } ,
99- } ;
100- } catch ( err ) {
101- console . error ( `[analytics] Error loading analytics for user ${ userId } :` , err ) ;
102- // Return empty data on error rather than crashing
103- return {
104- stats : [ ] ,
105- insights : {
106- totalMessages : 0 ,
107- totalCost : 0 ,
108- avgRating : null ,
109- mostUsedModel : null ,
110- bestRatedModel : null ,
111- mostCostEffective : null ,
112- } ,
113- } ;
114- }
94+ return {
95+ stats,
96+ insights : {
97+ totalMessages,
98+ totalCost,
99+ avgRating,
100+ mostUsedModel,
101+ bestRatedModel,
102+ mostCostEffective,
103+ fastestModel,
104+ } ,
105+ } ;
106+ } catch ( err ) {
107+ console . error ( `[analytics] Error loading analytics for user ${ userId } :` , err ) ;
108+ // Return empty data on error rather than crashing
109+ return {
110+ stats : [ ] ,
111+ insights : {
112+ totalMessages : 0 ,
113+ totalCost : 0 ,
114+ avgRating : null ,
115+ mostUsedModel : null ,
116+ bestRatedModel : null ,
117+ mostCostEffective : null ,
118+ } ,
119+ } ;
120+ }
115121} ;
0 commit comments