fix hf cfg/split ui
This commit is contained in:
parent
eb2ba90a03
commit
ef9e5ffc33
5 changed files with 315 additions and 265 deletions
|
|
@ -35,11 +35,10 @@ import {
|
|||
import {
|
||||
useDebouncedValue,
|
||||
useHfDatasetSearch,
|
||||
useHfDatasetSplits,
|
||||
useInfiniteScroll,
|
||||
} from "@/hooks";
|
||||
import { cn, formatCompact } from "@/lib/utils";
|
||||
import { useTrainingConfigStore } from "@/features/training";
|
||||
import { HfDatasetConfigSplitSelectors, useTrainingConfigStore } from "@/features/training";
|
||||
import type { DatasetFormat } from "@/types/training";
|
||||
import {
|
||||
InformationCircleIcon,
|
||||
|
|
@ -48,7 +47,7 @@ import {
|
|||
Upload04Icon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { useShallow } from "zustand/react/shallow";
|
||||
|
||||
const FORMAT_OPTIONS: { value: DatasetFormat; label: string }[] = [
|
||||
|
|
@ -113,39 +112,6 @@ export function DatasetStep() {
|
|||
hfResults.length,
|
||||
);
|
||||
|
||||
// Fetch configs & splits from HF datasets-server API
|
||||
const {
|
||||
configs: hfConfigs,
|
||||
splits: hfSplits,
|
||||
hasMultipleConfigs,
|
||||
hasMultipleSplits,
|
||||
isLoading: splitsLoading,
|
||||
error: splitsError,
|
||||
} = useHfDatasetSplits(
|
||||
datasetSource === "huggingface" ? dataset : null,
|
||||
datasetConfig,
|
||||
{ accessToken: hfToken || undefined },
|
||||
);
|
||||
|
||||
// Auto-select config when there is only one
|
||||
useEffect(() => {
|
||||
if (hfConfigs.length === 1 && datasetConfig !== hfConfigs[0]) {
|
||||
setDatasetConfig(hfConfigs[0]);
|
||||
}
|
||||
}, [hfConfigs, datasetConfig, setDatasetConfig]);
|
||||
|
||||
// Auto-select split when there is only one, or default to "train"
|
||||
useEffect(() => {
|
||||
if (hfSplits.length === 0) return;
|
||||
if (hfSplits.length === 1 && datasetSplit !== hfSplits[0]) {
|
||||
setDatasetSplit(hfSplits[0]);
|
||||
} else if (!datasetSplit && hfSplits.includes("train")) {
|
||||
setDatasetSplit("train");
|
||||
} else if (!datasetSplit) {
|
||||
setDatasetSplit(hfSplits[0]);
|
||||
}
|
||||
}, [hfSplits, datasetSplit, setDatasetSplit]);
|
||||
|
||||
const handleFileUpload = () => {
|
||||
setUploadedFile("my_dataset.jsonl");
|
||||
};
|
||||
|
|
@ -304,98 +270,16 @@ export function DatasetStep() {
|
|||
</div>
|
||||
</Field>
|
||||
|
||||
{/* Config & Split selectors */}
|
||||
{dataset && splitsLoading && (
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground py-1">
|
||||
<Spinner className="size-3.5" />
|
||||
Loading dataset configs and splits...
|
||||
</div>
|
||||
)}
|
||||
|
||||
{dataset && splitsError && (
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-400">
|
||||
Could not fetch dataset splits: {splitsError}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{dataset && !splitsLoading && !splitsError && hasMultipleConfigs && (
|
||||
<Field>
|
||||
<FieldLabel className="flex items-center gap-1.5">
|
||||
Subset (Config)
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-muted-foreground/50 hover:text-muted-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3.5"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
This dataset has multiple subsets (configurations).
|
||||
Select which one to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</FieldLabel>
|
||||
<Select
|
||||
value={datasetConfig ?? ""}
|
||||
onValueChange={(v) => setDatasetConfig(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a subset..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfConfigs.map((cfg) => (
|
||||
<SelectItem key={cfg} value={cfg}>
|
||||
{cfg}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
)}
|
||||
|
||||
{dataset && !splitsLoading && !splitsError && hasMultipleSplits && (
|
||||
<Field>
|
||||
<FieldLabel className="flex items-center gap-1.5">
|
||||
Split
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-muted-foreground/50 hover:text-muted-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3.5"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
Select which split of the dataset to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</FieldLabel>
|
||||
<Select
|
||||
value={datasetSplit ?? ""}
|
||||
onValueChange={(v) => setDatasetSplit(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a split..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfSplits.map((split) => (
|
||||
<SelectItem key={split} value={split}>
|
||||
{split}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
)}
|
||||
<HfDatasetConfigSplitSelectors
|
||||
variant="wizard"
|
||||
enabled={datasetSource === "huggingface"}
|
||||
datasetName={dataset}
|
||||
accessToken={hfToken || undefined}
|
||||
datasetConfig={datasetConfig}
|
||||
setDatasetConfig={setDatasetConfig}
|
||||
datasetSplit={datasetSplit}
|
||||
setDatasetSplit={setDatasetSplit}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -25,11 +25,10 @@ import {
|
|||
import {
|
||||
useDebouncedValue,
|
||||
useHfDatasetSearch,
|
||||
useHfDatasetSplits,
|
||||
useInfiniteScroll,
|
||||
} from "@/hooks";
|
||||
import { formatCompact } from "@/lib/utils";
|
||||
import { useTrainingConfigStore } from "@/features/training";
|
||||
import { HfDatasetConfigSplitSelectors, useTrainingConfigStore } from "@/features/training";
|
||||
import {
|
||||
CloudUploadIcon,
|
||||
Database02Icon,
|
||||
|
|
@ -39,10 +38,20 @@ import {
|
|||
ViewIcon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { useShallow } from "zustand/react/shallow";
|
||||
import { DatasetPreviewDialog } from "./dataset-preview-dialog";
|
||||
|
||||
function isLikelyLocalDatasetRef(value: string) {
|
||||
return (
|
||||
value.startsWith("/") ||
|
||||
value.startsWith("./") ||
|
||||
value.startsWith("../") ||
|
||||
value.includes("\\") ||
|
||||
/\.(jsonl|json|csv|parquet)$/i.test(value)
|
||||
);
|
||||
}
|
||||
|
||||
export function DatasetSection() {
|
||||
const {
|
||||
dataset,
|
||||
|
|
@ -102,37 +111,6 @@ export function DatasetSection() {
|
|||
return ids;
|
||||
}, [hfResults, dataset]);
|
||||
|
||||
// Fetch configs & splits from HF datasets-server API
|
||||
const {
|
||||
configs: hfConfigs,
|
||||
splits: hfSplits,
|
||||
hasMultipleConfigs,
|
||||
hasMultipleSplits,
|
||||
isLoading: splitsLoading,
|
||||
error: splitsError,
|
||||
} = useHfDatasetSplits(dataset, datasetConfig, {
|
||||
accessToken: hfToken || undefined,
|
||||
});
|
||||
|
||||
// Auto-select config when there is only one
|
||||
useEffect(() => {
|
||||
if (hfConfigs.length === 1 && datasetConfig !== hfConfigs[0]) {
|
||||
setDatasetConfig(hfConfigs[0]);
|
||||
}
|
||||
}, [hfConfigs, datasetConfig, setDatasetConfig]);
|
||||
|
||||
// Auto-select split when there is only one, or default to "train" if available
|
||||
useEffect(() => {
|
||||
if (hfSplits.length === 0) return;
|
||||
if (hfSplits.length === 1 && datasetSplit !== hfSplits[0]) {
|
||||
setDatasetSplit(hfSplits[0]);
|
||||
} else if (!datasetSplit && hfSplits.includes("train")) {
|
||||
setDatasetSplit("train");
|
||||
} else if (!datasetSplit) {
|
||||
setDatasetSplit(hfSplits[0]);
|
||||
}
|
||||
}, [hfSplits, datasetSplit, setDatasetSplit]);
|
||||
|
||||
const comboboxAnchorRef = useRef<HTMLDivElement>(null);
|
||||
const { scrollRef, sentinelRef } = useInfiniteScroll(
|
||||
fetchMore,
|
||||
|
|
@ -258,104 +236,16 @@ export function DatasetSection() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Config & Split selectors - shown after dataset is selected */}
|
||||
{dataset && !splitsLoading && !splitsError && (hasMultipleConfigs || hasMultipleSplits) && (
|
||||
<div className="flex flex-col gap-3 rounded-lg border bg-muted/20 px-3.5 py-3">
|
||||
{hasMultipleConfigs && (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
||||
Subset (Config)
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-foreground/70 hover:text-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
This dataset has multiple subsets (configurations).
|
||||
Select which one to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</span>
|
||||
<Select
|
||||
value={datasetConfig ?? ""}
|
||||
onValueChange={(v) => setDatasetConfig(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a subset..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfConfigs.map((cfg) => (
|
||||
<SelectItem key={cfg} value={cfg}>
|
||||
{cfg}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasMultipleSplits && (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
||||
Split
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-foreground/70 hover:text-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Select which split of the dataset to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</span>
|
||||
<Select
|
||||
value={datasetSplit ?? ""}
|
||||
onValueChange={(v) => setDatasetSplit(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a split..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfSplits.map((split) => (
|
||||
<SelectItem key={split} value={split}>
|
||||
{split}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Loading indicator for splits */}
|
||||
{dataset && splitsLoading && (
|
||||
<div className="flex items-center gap-2 rounded-lg border bg-muted/20 px-3.5 py-3 text-xs text-muted-foreground">
|
||||
<Spinner className="size-3.5" />
|
||||
Loading dataset configs and splits...
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Error fetching splits */}
|
||||
{dataset && splitsError && (
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50 px-3.5 py-2.5 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-400">
|
||||
Could not fetch dataset splits: {splitsError}
|
||||
</div>
|
||||
)}
|
||||
<HfDatasetConfigSplitSelectors
|
||||
variant="studio"
|
||||
enabled={!!dataset && !isLikelyLocalDatasetRef(dataset)}
|
||||
datasetName={dataset}
|
||||
accessToken={hfToken || undefined}
|
||||
datasetConfig={datasetConfig}
|
||||
setDatasetConfig={setDatasetConfig}
|
||||
datasetSplit={datasetSplit}
|
||||
setDatasetSplit={setDatasetSplit}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,271 @@
|
|||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import {
|
||||
Field,
|
||||
FieldLabel,
|
||||
} from "@/components/ui/field";
|
||||
import { useHfDatasetSplits } from "@/hooks";
|
||||
import { InformationCircleIcon } from "@hugeicons/core-free-icons";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { useEffect } from "react";
|
||||
|
||||
type Props = {
|
||||
variant: "wizard" | "studio";
|
||||
enabled: boolean;
|
||||
datasetName: string | null;
|
||||
accessToken?: string;
|
||||
datasetConfig: string | null;
|
||||
setDatasetConfig: (v: string | null) => void;
|
||||
datasetSplit: string | null;
|
||||
setDatasetSplit: (v: string | null) => void;
|
||||
};
|
||||
|
||||
export function HfDatasetConfigSplitSelectors({
|
||||
variant,
|
||||
enabled,
|
||||
datasetName,
|
||||
accessToken,
|
||||
datasetConfig,
|
||||
setDatasetConfig,
|
||||
datasetSplit,
|
||||
setDatasetSplit,
|
||||
}: Props) {
|
||||
const {
|
||||
configs: hfConfigs,
|
||||
splits: hfSplits,
|
||||
hasMultipleConfigs,
|
||||
hasMultipleSplits,
|
||||
isLoading,
|
||||
error,
|
||||
} = useHfDatasetSplits(enabled ? datasetName : null, datasetConfig, {
|
||||
accessToken,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (hfConfigs.length === 1 && datasetConfig !== hfConfigs[0]) {
|
||||
setDatasetConfig(hfConfigs[0]);
|
||||
}
|
||||
}, [hfConfigs, datasetConfig, setDatasetConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (hfSplits.length === 0) return;
|
||||
if (hasMultipleConfigs && !datasetConfig) return;
|
||||
if (hfSplits.length === 1 && datasetSplit !== hfSplits[0]) {
|
||||
setDatasetSplit(hfSplits[0]);
|
||||
} else if (!datasetSplit && hfSplits.includes("train")) {
|
||||
setDatasetSplit("train");
|
||||
} else if (!datasetSplit) {
|
||||
setDatasetSplit(hfSplits[0]);
|
||||
}
|
||||
}, [
|
||||
hfSplits,
|
||||
hasMultipleConfigs,
|
||||
datasetConfig,
|
||||
datasetSplit,
|
||||
setDatasetSplit,
|
||||
]);
|
||||
|
||||
if (!enabled || !datasetName) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading && (
|
||||
<div
|
||||
className={
|
||||
variant === "wizard"
|
||||
? "flex items-center gap-2 text-xs text-muted-foreground py-1"
|
||||
: "flex items-center gap-2 rounded-lg border bg-muted/20 px-3.5 py-3 text-xs text-muted-foreground"
|
||||
}
|
||||
>
|
||||
<Spinner className="size-3.5" />
|
||||
Loading dataset configs and splits...
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div
|
||||
className={
|
||||
variant === "wizard"
|
||||
? "rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-400"
|
||||
: "rounded-lg border border-amber-200 bg-amber-50 px-3.5 py-2.5 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-400"
|
||||
}
|
||||
>
|
||||
Could not fetch dataset splits: {error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isLoading && !error && hasMultipleConfigs && (
|
||||
<>
|
||||
{variant === "wizard" ? (
|
||||
<Field>
|
||||
<FieldLabel className="flex items-center gap-1.5">
|
||||
Subset (Config)
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-muted-foreground/50 hover:text-muted-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3.5"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
This dataset has multiple subsets (configurations). Select
|
||||
which one to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</FieldLabel>
|
||||
<Select
|
||||
value={datasetConfig ?? ""}
|
||||
onValueChange={(v) => setDatasetConfig(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a subset..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfConfigs.map((cfg) => (
|
||||
<SelectItem key={cfg} value={cfg}>
|
||||
{cfg}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
) : (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
||||
Subset (Config)
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-foreground/70 hover:text-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
This dataset has multiple subsets (configurations). Select
|
||||
which one to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</span>
|
||||
<Select
|
||||
value={datasetConfig ?? ""}
|
||||
onValueChange={(v) => setDatasetConfig(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a subset..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfConfigs.map((cfg) => (
|
||||
<SelectItem key={cfg} value={cfg}>
|
||||
{cfg}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{!isLoading && !error && hasMultipleSplits && (
|
||||
<>
|
||||
{variant === "wizard" ? (
|
||||
<Field>
|
||||
<FieldLabel className="flex items-center gap-1.5">
|
||||
Split
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-muted-foreground/50 hover:text-muted-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3.5"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-xs">
|
||||
Select which split of the dataset to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</FieldLabel>
|
||||
<Select
|
||||
value={datasetSplit ?? ""}
|
||||
onValueChange={(v) => setDatasetSplit(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a split..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfSplits.map((split) => (
|
||||
<SelectItem key={split} value={split}>
|
||||
{split}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
) : (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
||||
Split
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<button
|
||||
type="button"
|
||||
className="text-foreground/70 hover:text-foreground"
|
||||
>
|
||||
<HugeiconsIcon
|
||||
icon={InformationCircleIcon}
|
||||
className="size-3"
|
||||
/>
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Select which split of the dataset to use for training.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</span>
|
||||
<Select
|
||||
value={datasetSplit ?? ""}
|
||||
onValueChange={(v) => setDatasetSplit(v || null)}
|
||||
>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder="Select a split..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{hfSplits.map((split) => (
|
||||
<SelectItem key={split} value={split}>
|
||||
{split}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -5,4 +5,5 @@ export {
|
|||
} from "./stores/training-runtime-store";
|
||||
export { useTrainingActions } from "./hooks/use-training-actions";
|
||||
export { useTrainingRuntimeLifecycle } from "./hooks/use-training-runtime-lifecycle";
|
||||
export { HfDatasetConfigSplitSelectors } from "./components/hf-dataset-config-split-selectors";
|
||||
export type { TrainingPhase } from "./types/runtime";
|
||||
|
|
|
|||
|
|
@ -117,10 +117,14 @@ export function useHfDatasetSplits(
|
|||
// Derive unique configs
|
||||
const configs = Array.from(new Set(entries.map((e) => e.config)));
|
||||
|
||||
// Derive splits for the selected config (or all splits if no config selected)
|
||||
const filteredEntries = selectedConfig
|
||||
? entries.filter((e) => e.config === selectedConfig)
|
||||
: entries;
|
||||
// Derive splits for the active config.
|
||||
// If dataset has >1 config and none is selected yet, return no splits so UI
|
||||
// doesn't auto-pick/show a split before config is chosen.
|
||||
const activeConfig =
|
||||
selectedConfig ?? (configs.length === 1 ? configs[0] : null);
|
||||
const filteredEntries = activeConfig
|
||||
? entries.filter((e) => e.config === activeConfig)
|
||||
: [];
|
||||
const splits = Array.from(new Set(filteredEntries.map((e) => e.split)));
|
||||
|
||||
return {
|
||||
|
|
@ -128,7 +132,7 @@ export function useHfDatasetSplits(
|
|||
splits,
|
||||
entries,
|
||||
hasMultipleConfigs: configs.length > 1,
|
||||
hasMultipleSplits: splits.length > 1,
|
||||
hasMultipleSplits: activeConfig ? splits.length > 1 : false,
|
||||
isLoading,
|
||||
error,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue