Skip to content

Commit 14a616e

Browse files
refactored UI function config access to use a hook / helper (tensorzero#2910)
* refactored UI function config access to use a hook / helper * made hook / helper for getting all functions --------- Co-authored-by: Gabriel Bianconi <1275491+GabrielBianconi@users.noreply.github.com>
1 parent 24f199f commit 14a616e

File tree

27 files changed

+216
-154
lines changed

27 files changed

+216
-154
lines changed

ui/app/components/function/FunctionInfo.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Code } from "~/components/ui/code";
2-
import { useConfig } from "~/context/config";
2+
import { useFunctionConfig } from "~/context/config";
33
import { AlertDialog } from "~/components/ui/AlertDialog";
44
import type { FunctionConfig } from "tensorzero-node";
55
import { FunctionLink } from "./FunctionLink";
@@ -13,8 +13,7 @@ export function FunctionInfo({
1313
functionName,
1414
functionType,
1515
}: FunctionInfoProps) {
16-
const config = useConfig();
17-
const functionConfig = config.functions[functionName];
16+
const functionConfig = useFunctionConfig(functionName);
1817

1918
return (
2019
<>

ui/app/components/function/FunctionLink.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Link } from "react-router";
22
import { AlertDialog } from "~/components/ui/AlertDialog";
3-
import { useConfig } from "~/context/config";
3+
import { useFunctionConfig } from "~/context/config";
44
import type { ReactNode } from "react";
55

66
type FunctionLinkProps = {
@@ -9,8 +9,7 @@ type FunctionLinkProps = {
99
};
1010

1111
export function FunctionLink({ functionName, children }: FunctionLinkProps) {
12-
const config = useConfig();
13-
const functionConfig = config.functions[functionName];
12+
const functionConfig = useFunctionConfig(functionName);
1413
return functionConfig ? (
1514
<Link to={`/observability/functions/${functionName}`}>{children}</Link>
1615
) : (

ui/app/components/function/variant/VariantLink.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Link } from "react-router";
22
import { AlertDialog } from "~/components/ui/AlertDialog";
3-
import { useConfig } from "~/context/config";
3+
import { useFunctionConfig } from "~/context/config";
44
import type { ReactNode } from "react";
55

66
type VariantLinkProps = {
@@ -14,8 +14,7 @@ export function VariantLink({
1414
functionName,
1515
children,
1616
}: VariantLinkProps) {
17-
const config = useConfig();
18-
const functionConfig = config.functions[functionName];
17+
const functionConfig = useFunctionConfig(functionName);
1918
const variantConfig = functionConfig?.variants[variantName];
2019
return variantConfig ? (
2120
<Link

ui/app/components/ui/TableItems.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "./tooltip";
88
import { getFunctionTypeIcon } from "~/utils/icon";
99
import { formatDate } from "~/utils/date";
10-
import { useConfig } from "~/context/config";
10+
import { useFunctionConfig } from "~/context/config";
1111
import { AlertDialog } from "~/components/ui/AlertDialog";
1212

1313
interface TableItemShortUuidProps {
@@ -77,9 +77,8 @@ function TableItemFunction({
7777
functionType,
7878
link,
7979
}: TableItemFunctionProps) {
80-
const config = useConfig();
8180
const functionIconConfig = getFunctionTypeIcon(functionType);
82-
const functionConfig = config.functions[functionName];
81+
const functionConfig = useFunctionConfig(functionName);
8382

8483
const baseClasses =
8584
"flex items-center text-sm text-fg-primary gap-2 rounded-md font-mono";

ui/app/context/config.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,29 @@ export function useConfig() {
2121
return config;
2222
}
2323

24+
/**
25+
* Hook to get a specific function configuration by name
26+
* @param functionName - The name of the function to retrieve
27+
* @returns The function configuration object or null if not found
28+
*/
29+
export function useFunctionConfig(functionName: string | null) {
30+
const config = useConfig();
31+
if (!functionName) {
32+
return null;
33+
}
34+
// eslint-disable-next-line no-restricted-syntax
35+
return config.functions[functionName] || null;
36+
}
37+
/**
38+
* Hook to get all function configs
39+
* @returns The function configuration object or null if not found
40+
*/
41+
export function useAllFunctionConfigs() {
42+
const config = useConfig();
43+
// eslint-disable-next-line no-restricted-syntax
44+
return config.functions;
45+
}
46+
2447
export function ConfigProvider({
2548
children,
2649
value,

ui/app/routes/api/curated_inferences/count.route.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from "~/utils/clickhouse/curation.server";
77
import { countInferencesForFunction } from "~/utils/clickhouse/inference.server";
88
import { getFeedbackConfig } from "~/utils/config/feedback";
9-
import { getConfig } from "~/utils/config/index.server";
9+
import { getConfig, getFunctionConfig } from "~/utils/config/index.server";
1010

1111
/// Count the number of inferences, feedbacks, and curated inferences for a given function and metric
1212
/// This is used to determine the number of inferences to display in the UI
@@ -23,7 +23,9 @@ export async function loader({
2323
const threshold = parseFloat(url.searchParams.get("threshold") || "0");
2424

2525
const config = await getConfig();
26-
const functionConfig = config.functions[functionName || ""];
26+
const functionConfig = functionName
27+
? await getFunctionConfig(functionName, config)
28+
: null;
2729
if (functionName && !functionConfig) {
2830
throw data(`Function ${functionName} not found in config`, { status: 404 });
2931
}

ui/app/routes/api/function/$function_name/feedback_counts.route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { data, type LoaderFunctionArgs } from "react-router";
2-
import { getConfig } from "~/utils/config/index.server";
2+
import { getConfig, getFunctionConfig } from "~/utils/config/index.server";
33
import { getInferenceTableName } from "~/utils/clickhouse/common";
44
import {
55
queryMetricsWithFeedback,
@@ -18,7 +18,7 @@ export async function loader({
1818

1919
try {
2020
const config = await getConfig();
21-
const functionConfig = config.functions[functionName];
21+
const functionConfig = await getFunctionConfig(functionName, config);
2222
if (!functionConfig) {
2323
throw data(`Function ${functionName} not found in config`, {
2424
status: 404,

ui/app/routes/datasets/$dataset_name/datapoint/$id/DatapointBasicInfo.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useConfig } from "~/context/config";
1+
import { useFunctionConfig } from "~/context/config";
22
import type { ParsedDatasetRow } from "~/utils/clickhouse/datasets";
33
import {
44
BasicInfoLayout,
@@ -30,8 +30,7 @@ const createTimestampTooltip = (timestamp: string | number | Date) => {
3030
};
3131

3232
export default function DatapointBasicInfo({ datapoint }: BasicInfoProps) {
33-
const config = useConfig();
34-
const function_config = config.functions[datapoint.function_name];
33+
const function_config = useFunctionConfig(datapoint.function_name);
3534
const type = function_config?.type;
3635
if (!type) {
3736
throw new Error(`Function ${datapoint.function_name} not found`);

ui/app/routes/datasets/$dataset_name/datapoint/$id/route.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
SectionsGroup,
2222
} from "~/components/layout/PageLayout";
2323
import { Badge } from "~/components/ui/badge";
24-
import { useConfig } from "~/context/config";
24+
import { useFunctionConfig } from "~/context/config";
2525
import { resolvedInputToTensorZeroInput } from "~/routes/api/tensorzero/inference";
2626
import {
2727
prepareInferenceActionRequest,
@@ -37,7 +37,7 @@ import {
3737
getDatasetCounts,
3838
staleDatapoint,
3939
} from "~/utils/clickhouse/datasets.server";
40-
import { getConfig } from "~/utils/config/index.server";
40+
import { getConfig, getFunctionConfig } from "~/utils/config/index.server";
4141
import { logger } from "~/utils/logger";
4242
import { getTensorZeroClient } from "~/utils/tensorzero.server";
4343
import type { Route } from "./+types/route";
@@ -77,7 +77,10 @@ export async function action({ request }: ActionFunctionArgs) {
7777
const parsedFormData: ParsedDatasetRow =
7878
ParsedDatasetRowSchema.parse(cleanedData);
7979
const config = await getConfig();
80-
const functionConfig = config.functions[parsedFormData.function_name];
80+
const functionConfig = await getFunctionConfig(
81+
parsedFormData.function_name,
82+
config,
83+
);
8184
if (!functionConfig) {
8285
return new Response(
8386
`Failed to find function config for function ${parsedFormData.function_name}`,
@@ -198,7 +201,6 @@ export default function DatapointPage({ loaderData }: Route.ComponentProps) {
198201
const [output, setOutput] = useState<typeof datapoint.output>(
199202
datapoint.output,
200203
);
201-
const config = useConfig();
202204
const [isEditing, setIsEditing] = useState(false);
203205

204206
const canSave = useMemo(() => {
@@ -259,9 +261,8 @@ export default function DatapointPage({ loaderData }: Route.ComponentProps) {
259261
}
260262
};
261263

262-
const variants = Object.keys(
263-
config.functions[datapoint.function_name]?.variants || {},
264-
);
264+
const functionConfig = useFunctionConfig(datapoint.function_name);
265+
const variants = Object.keys(functionConfig?.variants || {});
265266

266267
const variantInferenceFetcher = useInferenceActionFetcher();
267268
const variantSource = "datapoint";

ui/app/routes/datasets/builder/DatasetBuilderForm.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import {
66
} from "./types";
77
import { FunctionFormField } from "~/components/function/FunctionFormField";
88
import { DatasetFormField } from "~/components/dataset/DatasetFormField";
9-
import { useConfig } from "~/context/config";
9+
import {
10+
useAllFunctionConfigs,
11+
useConfig,
12+
useFunctionConfig,
13+
} from "~/context/config";
1014
import CurationMetricSelector from "~/components/metric/CurationMetricSelector";
1115
import { useCountFetcher } from "~/routes/api/curated_inferences/count.route";
1216
import { useFetcher } from "react-router";
@@ -54,14 +58,16 @@ export function DatasetBuilderForm() {
5458
metricName: metricName ?? undefined,
5559
threshold: threshold ?? undefined,
5660
});
61+
const functionConfig = useFunctionConfig(functionName ?? "");
62+
5763
useEffect(() => {
5864
const metricConfig = config.metrics[metricName ?? ""];
5965
form.setValue("metric_config", metricConfig ? metricConfig : undefined);
60-
const functionType = config.functions[functionName ?? ""]?.type;
66+
const functionType = functionConfig?.type;
6167
if (functionType) {
6268
form.setValue("type", functionType);
6369
}
64-
}, [metricName, functionName, config, form]);
70+
}, [metricName, functionName, config, form, functionConfig]);
6571

6672
// Handle form submission response
6773
useEffect(() => {
@@ -132,7 +138,7 @@ export function DatasetBuilderForm() {
132138
<FunctionFormField
133139
control={form.control}
134140
name="function"
135-
functions={config.functions}
141+
functions={useAllFunctionConfigs()}
136142
onSelect={() => {
137143
form.resetField("variant");
138144
}}

0 commit comments

Comments
 (0)