Skip to content

Commit a59466d

Browse files
densumeshcdxker
authored andcommitted
feature: headless analytics
1 parent c2db61c commit a59466d

File tree

12 files changed

+580
-206
lines changed

12 files changed

+580
-206
lines changed

frontends/dashboard/src/analytics/components/SingleQueryInfo/ResultCard.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { SearchQueryEvent } from "shared/types";
1+
import { ScoreChunkDTO } from "shared/types";
22
import { FullScreenModal, JsonInput } from "shared/ui";
33
import { IoCode } from "solid-icons/io";
44
import { createMemo, createSignal, Show } from "solid-js";
55
import { z } from "zod";
66

77
interface ResultCardProps {
8-
result: SearchQueryEvent["results"][0];
8+
result: ScoreChunkDTO;
99
}
1010

1111
const usefulMetadataSchema = z.object({
@@ -43,7 +43,7 @@ export const ResultCard = (props: ResultCardProps) => {
4343

4444
<IoCode />
4545
</div>
46-
<Show when={props?.result?.score}>
46+
<Show when={props.result.score}>
4747
<div class="text-xs font-normal opacity-60">
4848
Score: {props?.result?.score?.toFixed(5)}
4949
</div>

frontends/dashboard/src/analytics/components/SingleQueryInfo/index.tsx

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { DataSquare } from "./DataSquare";
1010
import { DatasetContext } from "../../../contexts/DatasetContext";
1111
import { UserContext } from "../../../contexts/UserContext";
1212
import { IoArrowBackOutline } from "solid-icons/io";
13+
import { isScoreChunkDTO } from "shared/types";
1314

1415
interface SingleQueryProps {
1516
queryId: string;
@@ -59,46 +60,74 @@ export const SingleQuery = (props: SingleQueryProps) => {
5960
label="Dataset"
6061
value={datasetName() || props.data.dataset_id}
6162
/>
62-
<DataSquare label="Results" value={props.data.results.length} />
63-
<DataSquare label="Latency" value={`${props.data.latency}ms`} />
64-
<DataSquare
65-
label="Top Score"
66-
value={props.data.top_score.toPrecision(4)}
67-
/>
68-
<Show when={props.data.query_rating}>
63+
<Show when={props.data.results && props.data.results[0]}>
64+
<DataSquare label="Results" value={props.data.results.length} />
65+
</Show>
66+
<Show when={props.data.latency > 0.0}>
67+
<DataSquare label="Latency" value={`${props.data.latency}ms`} />
68+
</Show>
69+
<Show when={props.data.top_score > 0.0}>
70+
<DataSquare
71+
label="Top Score"
72+
value={props.data.top_score.toPrecision(4)}
73+
/>
74+
</Show>
75+
<Show
76+
when={
77+
props.data.query_rating &&
78+
(props.data.query_rating.rating > 0 ||
79+
props.data.query_rating.note)
80+
}
81+
>
6982
<DataSquare
7083
label="User Rating"
7184
value={props.data.query_rating?.rating.toString() ?? "N/A"}
7285
/>
7386
</Show>
7487
</dl>
7588
</div>
76-
<Card title="Results">
77-
<div class="grid gap-4 sm:grid-cols-2">
78-
<For
79-
fallback={<div class="py-8 text-center">No Data.</div>}
80-
each={props.data.results}
81-
>
82-
{(result) => <ResultCard result={result} />}
83-
</For>
84-
</div>
85-
</Card>
86-
<Card title="Request Parameters">
87-
<ul>
88-
<For
89-
each={Object.keys(props.data.request_params).filter(
90-
(key) => props.data.request_params[key],
91-
)}
92-
>
93-
{(key) => (
94-
<li class="text-sm">
95-
<span class="font-medium">{key}: </span>
96-
{props.data.request_params[key] as string}{" "}
97-
</li>
98-
)}
99-
</For>
100-
</ul>
101-
</Card>
89+
<Show when={props.data.results && props.data.results[0]}>
90+
<Card title="Results">
91+
<div class="grid gap-4 sm:grid-cols-2">
92+
<For
93+
fallback={<div class="py-8 text-center">No Data.</div>}
94+
each={props.data.results}
95+
>
96+
{(result) => {
97+
if (isScoreChunkDTO(result)) {
98+
return <ResultCard result={result} />;
99+
} else {
100+
return (
101+
<div>
102+
<pre class="text-sm">
103+
{JSON.stringify(result, null, 2)}
104+
</pre>
105+
</div>
106+
);
107+
}
108+
}}
109+
</For>
110+
</div>
111+
</Card>
112+
</Show>
113+
<Show when={props.data.request_params}>
114+
<Card title="Request Parameters">
115+
<ul>
116+
<For
117+
each={Object.keys(props.data.request_params).filter(
118+
(key) => props.data.request_params[key],
119+
)}
120+
>
121+
{(key) => (
122+
<li class="text-sm">
123+
<span class="font-medium">{key}: </span>
124+
{props.data.request_params[key] as string}{" "}
125+
</li>
126+
)}
127+
</For>
128+
</ul>
129+
</Card>
130+
</Show>
102131
</div>
103132
);
104133
};

frontends/dashboard/src/analytics/components/SingleRagInfo/index.tsx

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { createQuery } from "@tanstack/solid-query";
1+
/* eslint-disable @typescript-eslint/no-unsafe-call */
2+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
3+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
4+
import { createQuery, CreateQueryResult } from "@tanstack/solid-query";
25
import { getRagQuery, getSearchQuery } from "../../api/analytics";
36
import { createMemo, For, Show, useContext } from "solid-js";
47
import { format } from "date-fns";
@@ -10,6 +13,7 @@ import { DataSquare } from "../SingleQueryInfo/DataSquare";
1013
import { DatasetContext } from "../../../contexts/DatasetContext";
1114
import { UserContext } from "../../../contexts/UserContext";
1215
import { IoArrowBackOutline } from "solid-icons/io";
16+
import { isScoreChunkDTO, SearchQueryEvent } from "shared/types";
1317

1418
interface SingleRAGQueryProps {
1519
queryId: string;
@@ -24,19 +28,22 @@ export const SingleRAGQuery = (props: SingleRAGQueryProps) => {
2428
},
2529
}));
2630

27-
const search_query = createQuery(() => ({
28-
queryKey: ["single_query", rag_query.data?.search_id],
29-
queryFn: () => {
30-
return getSearchQuery(
31-
dataset.datasetId(),
32-
rag_query.data?.search_id ?? "",
33-
);
34-
},
35-
}));
31+
let search_query: CreateQueryResult<SearchQueryEvent, Error> | undefined;
32+
if (rag_query.data?.search_id !== "00000000-0000-0000-0000-000000000000") {
33+
search_query = createQuery(() => ({
34+
queryKey: ["single_query", rag_query.data?.search_id],
35+
queryFn: () => {
36+
return getSearchQuery(
37+
dataset.datasetId(),
38+
rag_query.data?.search_id ?? "",
39+
);
40+
},
41+
}));
42+
}
3643

3744
const DataDisplay = (props: {
3845
rag_data: NonNullable<typeof rag_query.data>;
39-
search_data: NonNullable<typeof search_query.data>;
46+
search_data?: SearchQueryEvent;
4047
}) => {
4148
const datasetName = createMemo(() => {
4249
const userContext = useContext(UserContext);
@@ -72,65 +79,102 @@ export const SingleRAGQuery = (props: SingleRAGQueryProps) => {
7279
label="Dataset"
7380
value={datasetName() || props.rag_data.dataset_id}
7481
/>
75-
<DataSquare
76-
label="Results"
77-
value={props.search_data.results.length}
78-
/>
79-
<DataSquare
80-
label="Top Score"
81-
value={props.search_data.top_score.toFixed(4)}
82-
/>
83-
<Show when={props.rag_data.query_rating}>
82+
<Show
83+
when={
84+
(props.search_data?.results && props.search_data.results[0]) ||
85+
(props.rag_data?.results && props.rag_data.results[0])
86+
}
87+
>
88+
<DataSquare
89+
label="Results"
90+
value={
91+
props.search_data
92+
? props.search_data.results.length
93+
: props.rag_data.results.length
94+
}
95+
/>
96+
</Show>
97+
<Show when={props.search_data && props.search_data.top_score > 0.0}>
98+
<DataSquare
99+
label="Top Score"
100+
value={props.search_data?.top_score.toPrecision(4) ?? "N/A"}
101+
/>
102+
</Show>
103+
<Show
104+
when={
105+
props.rag_data.query_rating &&
106+
(props.rag_data.query_rating.rating > 0 ||
107+
props.rag_data.query_rating.note)
108+
}
109+
>
84110
<DataSquare
85111
label="User Rating"
86112
value={props.rag_data.query_rating?.rating.toString() ?? "N/A"}
87113
/>
88114
</Show>
89115
</dl>
90116
</div>
91-
<Card title="LLM Response">
92-
<ul>
93-
<li>{props.rag_data.llm_response}</li>
94-
</ul>
95-
</Card>
96-
<Card title="Results">
97-
<div class="grid gap-4 sm:grid-cols-2">
98-
<For
99-
fallback={<div class="py-8 text-center">No Data.</div>}
100-
each={props.search_data.results}
101-
>
102-
{(result) => <ResultCard result={result} />}
103-
</For>
104-
</div>
105-
</Card>
106-
<Card title="Search Request Parameters">
107-
<ul>
108-
<For
109-
each={Object.keys(props.search_data.request_params).filter(
110-
(key) => props.search_data.request_params[key],
111-
)}
112-
>
113-
{(key) => (
114-
<li class="text-sm">
115-
<span class="font-medium">{key}: </span>
116-
{props.search_data.request_params[key] as string}{" "}
117-
</li>
118-
)}
119-
</For>
120-
</ul>
121-
</Card>
117+
<Show when={props.rag_data.llm_response}>
118+
<Card title="LLM Response">
119+
<ul>
120+
<li>{props.rag_data.llm_response}</li>
121+
</ul>
122+
</Card>
123+
</Show>
124+
<Show when={props.search_data?.results && props.search_data.results[0]}>
125+
<Card title="Results">
126+
<div class="grid gap-4 sm:grid-cols-2">
127+
<For
128+
fallback={<div class="py-8 text-center">No Data.</div>}
129+
each={
130+
props.search_data
131+
? props.search_data.results
132+
: props.rag_data.results
133+
}
134+
>
135+
{(result) => {
136+
if (isScoreChunkDTO(result)) {
137+
return <ResultCard result={result} />;
138+
} else {
139+
return (
140+
<div>
141+
<pre class="text-sm">
142+
{JSON.stringify(result, null, 2)}
143+
</pre>
144+
</div>
145+
);
146+
}
147+
}}
148+
</For>
149+
</div>
150+
</Card>
151+
</Show>
152+
<Show when={props.search_data && props.search_data.request_params}>
153+
<Card title="Search Request Parameters">
154+
<ul>
155+
<For
156+
each={Object.keys(
157+
props.search_data?.request_params ?? {},
158+
).filter((key) => props.search_data?.request_params[key])}
159+
>
160+
{(key) => (
161+
<li class="text-sm">
162+
<span class="font-medium">{key}: </span>
163+
{props.search_data?.request_params[key] as string}{" "}
164+
</li>
165+
)}
166+
</For>
167+
</ul>
168+
</Card>
169+
</Show>
122170
</div>
123171
);
124172
};
125173

126174
return (
127175
<Show when={rag_query.data}>
128176
{(rag_data) => (
129-
<Show when={search_query.data}>
130-
{(search_data) => (
131-
<DataDisplay rag_data={rag_data()} search_data={search_data()} />
132-
)}
133-
</Show>
177+
<DataDisplay rag_data={rag_data()} search_data={search_query?.data} />
134178
)}
135179
</Show>
136180
);

0 commit comments

Comments
 (0)