diff --git a/studio/frontend/src/features/studio/sections/config-summary-section.tsx b/studio/frontend/src/features/studio/sections/config-summary-section.tsx
deleted file mode 100644
index db85fdc11d..0000000000
--- a/studio/frontend/src/features/studio/sections/config-summary-section.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-import { SectionCard } from "@/components/section-card";
-import { Button } from "@/components/ui/button";
-import { useWizardStore } from "@/stores/training";
-import { Settings02Icon, StopIcon } from "@hugeicons/core-free-icons";
-import { HugeiconsIcon } from "@hugeicons/react";
-
-export function ConfigSummarySection() {
- const store = useWizardStore();
-
- const items = [
- {
- section: "Model",
- rows: [
- ["Model", store.selectedModel ?? "—"],
- ["Type", store.modelType ?? "—"],
- ["Method", store.trainingMethod],
- ],
- },
- {
- section: "Dataset",
- rows: [
- ["Source", store.datasetSource],
- ["Dataset", store.dataset ?? store.uploadedFile ?? "—"],
- ["Format", store.datasetFormat],
- ],
- },
- {
- section: "Hyperparams",
- rows: [
- ["Epochs", store.epochs],
- ["Batch size", store.batchSize],
- ["Learning rate", store.learningRate],
- ["Max steps", store.maxSteps],
- ["Context length", store.contextLength],
- ["Warmup steps", store.warmupSteps],
- ],
- },
- ...(store.trainingMethod !== "full"
- ? [
- {
- section: "LoRA",
- rows: [
- ["Rank", store.loraRank],
- ["Alpha", store.loraAlpha],
- ["Dropout", store.loraDropout],
- ["Variant", store.loraVariant],
- ],
- },
- ]
- : []),
- ];
-
- return (
-
}
- title="Config"
- description="Training configuration"
- accent="indigo"
- className="lg:col-span-4"
- >
-
- {items.map((group) => (
-
-
- {group.section}
-
- {group.rows.map(([label, value]) => (
-
- {String(label)}
-
- {String(value)}
-
-
- ))}
-
- ))}
-
-
-
-
- );
-}
diff --git a/studio/frontend/src/features/studio/sections/dataset-section.tsx b/studio/frontend/src/features/studio/sections/dataset-section.tsx
index b02330560b..0b2c2652ff 100644
--- a/studio/frontend/src/features/studio/sections/dataset-section.tsx
+++ b/studio/frontend/src/features/studio/sections/dataset-section.tsx
@@ -1,15 +1,14 @@
import { SectionCard } from "@/components/section-card";
import { Button } from "@/components/ui/button";
import {
- Collapsible,
- CollapsibleContent,
- CollapsibleTrigger,
-} from "@/components/ui/collapsible";
-import {
- InputGroup,
- InputGroupAddon,
- InputGroupInput,
-} from "@/components/ui/input-group";
+ Combobox,
+ ComboboxContent,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+} from "@/components/ui/combobox";
+import { InputGroupAddon } from "@/components/ui/input-group";
import {
Select,
SelectContent,
@@ -17,15 +16,20 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
+import { Spinner } from "@/components/ui/spinner";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
-import { DATASETS } from "@/config/training";
+import {
+ useDebouncedValue,
+ useHfDatasetSearch,
+ useInfiniteScroll,
+} from "@/hooks";
+import { formatCompact } from "@/lib/utils";
import { useWizardStore } from "@/stores/training";
import {
- ArrowDown01Icon,
CloudUploadIcon,
Database02Icon,
FileAttachmentIcon,
@@ -34,20 +38,55 @@ import {
ViewIcon,
} from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
-import { useState } from "react";
+import { useMemo, useRef, useState } from "react";
import { useShallow } from "zustand/react/shallow";
export function DatasetSection() {
- const { dataset, setDataset, datasetFormat, setDatasetFormat } =
+ const { dataset, setDataset, datasetFormat, setDatasetFormat, hfToken } =
useWizardStore(
- useShallow((s) => ({
- dataset: s.dataset,
- setDataset: s.setDataset,
- datasetFormat: s.datasetFormat,
- setDatasetFormat: s.setDatasetFormat,
+ useShallow(({ dataset, setDataset, datasetFormat, setDatasetFormat, hfToken }) => ({
+ dataset, setDataset, datasetFormat, setDatasetFormat, hfToken,
})),
);
- const [recOpen, setRecOpen] = useState(false);
+
+ const [inputValue, setInputValue] = useState("");
+ const selectingRef = useRef(false);
+ const debouncedQuery = useDebouncedValue(inputValue);
+
+ function handleDatasetSelect(id: string | null) {
+ selectingRef.current = true;
+ setDataset(id);
+ }
+
+ function handleInputChange(val: string) {
+ if (selectingRef.current) {
+ selectingRef.current = false;
+ return;
+ }
+ setInputValue(val);
+ }
+ const {
+ results: hfResults,
+ isLoading,
+ isLoadingMore,
+ fetchMore,
+ } = useHfDatasetSearch(debouncedQuery, {
+ accessToken: hfToken || undefined,
+ });
+
+ const resultIds = useMemo(() => {
+ const ids = hfResults.map((r) => r.id);
+ if (dataset && !ids.includes(dataset)) {
+ ids.unshift(dataset);
+ }
+ return ids;
+ }, [hfResults, dataset]);
+
+ const comboboxAnchorRef = useRef
(null);
+ const { scrollRef, sentinelRef } = useInfiniteScroll(
+ fetchMore,
+ hfResults.length,
+ );
return (
- {/* Load from Hub */}
Load from Hub
@@ -75,7 +113,8 @@ export function DatasetSection() {
- Enter a Hugging Face dataset path like 'username/dataset-name'.{" "}
+ Search Hugging Face datasets or enter a path like
+ 'username/dataset-name'.{" "}
-
-
-
-
- setDataset(e.target.value || null)}
- />
-
+
+
id}
+ autoHighlight={true}
+ >
+
+
+
+
+
+
+ {isLoading ? (
+
+ Searching...
+
+ ) : (
+ No datasets found
+ )}
+
+
+ {(id: string) => {
+ const r = hfResults.find((ds) => ds.id === id);
+ const detail = r?.totalExamples
+ ? `${formatCompact(r.totalExamples)} rows`
+ : r?.sizeCategory
+ ? r.sizeCategory
+ : r?.downloads != null
+ ? `↓${formatCompact(r.downloads)}`
+ : null;
+ return (
+
+
+
+
+ {id}
+
+
+
+ {id}
+
+
+ {detail && (
+
+ {detail}
+
+ )}
+
+ );
+ }}
+
+
+ {isLoadingMore && (
+
+
+
+ )}
+
+
+
+
- {/* Format */}
Dataset Format
@@ -146,7 +252,6 @@ export function DatasetSection() {
- {/* Active dataset display */}
{dataset ? (
@@ -176,42 +281,6 @@ export function DatasetSection() {
)}
- {/* Recommended */}
-
-
-
- Common Datasets
-
-
- {DATASETS.filter((d) => d.recommended).map((d) => (
-
- ))}
-
-
-
- {/* Action buttons */}