Implement ingest settings in UnifiedCloudPicker and IngestSettings components
- Added IngestSettings interface to define settings structure. - Integrated ingest settings state management in UnifiedCloudPicker. - Updated IngestSettings component to handle user input for chunk size, chunk overlap, OCR, and picture descriptions. - Passed settings and change handler to IngestSettings from UnifiedCloudPicker. - Enhanced UploadProviderPage to utilize ingest settings during file upload.
This commit is contained in:
parent
ce34c8ab0f
commit
e9de598a0f
4 changed files with 157 additions and 57 deletions
|
|
@ -5,6 +5,7 @@ import { useParams, useRouter } from "next/navigation";
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowLeft, AlertCircle } from "lucide-react";
|
||||
import { UnifiedCloudPicker, CloudFile } from "@/components/cloud-picker";
|
||||
import type { IngestSettings } from "@/components/cloud-picker/types";
|
||||
import { useTask } from "@/contexts/task-context";
|
||||
import { Toast } from "@/components/ui/toast";
|
||||
|
||||
|
|
@ -38,6 +39,13 @@ export default function UploadProviderPage() {
|
|||
null
|
||||
);
|
||||
const [showSuccessToast, setShowSuccessToast] = useState(false);
|
||||
const [ingestSettings, setIngestSettings] = useState<IngestSettings>({
|
||||
chunkSize: 1000,
|
||||
chunkOverlap: 200,
|
||||
ocr: false,
|
||||
pictureDescriptions: false,
|
||||
embeddingModel: "text-embedding-3-small",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchConnectorInfo = async () => {
|
||||
|
|
@ -167,9 +175,11 @@ export default function UploadProviderPage() {
|
|||
connection_id: string;
|
||||
max_files?: number;
|
||||
selected_files?: string[];
|
||||
settings?: IngestSettings;
|
||||
} = {
|
||||
connection_id: connector.connectionId,
|
||||
selected_files: selectedFiles.map(file => file.id),
|
||||
settings: ingestSettings,
|
||||
};
|
||||
|
||||
const response = await fetch(`/api/connectors/${connector.type}/sync`, {
|
||||
|
|
@ -337,6 +347,7 @@ export default function UploadProviderPage() {
|
|||
isAuthenticated={true}
|
||||
accessToken={accessToken || undefined}
|
||||
clientId={connector.clientId}
|
||||
onSettingsChange={setIngestSettings}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,75 +8,132 @@ import {
|
|||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import { ChevronRight, Info } from "lucide-react";
|
||||
import { IngestSettings as IngestSettingsType } from "./types";
|
||||
|
||||
interface IngestSettingsProps {
|
||||
isOpen: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
settings?: IngestSettingsType;
|
||||
onSettingsChange?: (settings: IngestSettingsType) => void;
|
||||
}
|
||||
|
||||
export const IngestSettings = ({
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
}: IngestSettingsProps) => (
|
||||
<Collapsible
|
||||
open={isOpen}
|
||||
onOpenChange={onOpenChange}
|
||||
className="border rounded-md p-4 border-muted-foreground/20"
|
||||
>
|
||||
<CollapsibleTrigger className="flex items-center gap-2 justify-between w-full -m-4 p-4 rounded-md transition-colors">
|
||||
<div className="flex items-center gap-2">
|
||||
<ChevronRight
|
||||
className={`h-4 w-4 text-muted-foreground transition-transform duration-200 ${
|
||||
isOpen ? "rotate-90" : ""
|
||||
}`}
|
||||
/>
|
||||
<span className="text-sm font-medium">Ingest settings</span>
|
||||
</div>
|
||||
</CollapsibleTrigger>
|
||||
settings,
|
||||
onSettingsChange,
|
||||
}: IngestSettingsProps) => {
|
||||
// Default settings
|
||||
const defaultSettings: IngestSettingsType = {
|
||||
chunkSize: 1000,
|
||||
chunkOverlap: 200,
|
||||
ocr: false,
|
||||
pictureDescriptions: false,
|
||||
embeddingModel: "text-embedding-3-small",
|
||||
};
|
||||
|
||||
<CollapsibleContent className="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-up-2 data-[state=open]:slide-down-2">
|
||||
<div className="pt-5 space-y-5">
|
||||
<div className="flex items-center gap-4 w-full">
|
||||
<div className="w-full">
|
||||
<div className="text-sm mb-2 font-semibold">Chunk size</div>
|
||||
<Input type="number" />
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="text-sm mb-2 font-semibold">Chunk overlap</div>
|
||||
<Input type="number" />
|
||||
</div>
|
||||
// Use provided settings or defaults
|
||||
const currentSettings = settings || defaultSettings;
|
||||
|
||||
const handleSettingsChange = (newSettings: Partial<IngestSettingsType>) => {
|
||||
const updatedSettings = { ...currentSettings, ...newSettings };
|
||||
onSettingsChange?.(updatedSettings);
|
||||
};
|
||||
|
||||
return (
|
||||
<Collapsible
|
||||
open={isOpen}
|
||||
onOpenChange={onOpenChange}
|
||||
className="border rounded-md p-4 border-muted-foreground/20"
|
||||
>
|
||||
<CollapsibleTrigger className="flex items-center gap-2 justify-between w-full -m-4 p-4 rounded-md transition-colors">
|
||||
<div className="flex items-center gap-2">
|
||||
<ChevronRight
|
||||
className={`h-4 w-4 text-muted-foreground transition-transform duration-200 ${
|
||||
isOpen ? "rotate-90" : ""
|
||||
}`}
|
||||
/>
|
||||
<span className="text-sm font-medium">Ingest settings</span>
|
||||
</div>
|
||||
</CollapsibleTrigger>
|
||||
|
||||
<CollapsibleContent className="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-up-2 data-[state=open]:slide-down-2">
|
||||
<div className="pt-5 space-y-5">
|
||||
<div className="flex items-center gap-4 w-full">
|
||||
<div className="w-full">
|
||||
<div className="text-sm mb-2 font-semibold">Chunk size</div>
|
||||
<Input
|
||||
type="number"
|
||||
value={currentSettings.chunkSize}
|
||||
onChange={e =>
|
||||
handleSettingsChange({
|
||||
chunkSize: parseInt(e.target.value) || 0,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="text-sm mb-2 font-semibold">Chunk overlap</div>
|
||||
<Input
|
||||
type="number"
|
||||
value={currentSettings.chunkOverlap}
|
||||
onChange={e =>
|
||||
handleSettingsChange({
|
||||
chunkOverlap: parseInt(e.target.value) || 0,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 items-center justify-between">
|
||||
<div>
|
||||
<div className="text-sm font-semibold pb-2">OCR</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Extracts text from images/PDFs. Ingest is slower when enabled.
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={currentSettings.ocr}
|
||||
onCheckedChange={checked =>
|
||||
handleSettingsChange({ ocr: checked })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 items-center justify-between">
|
||||
<div>
|
||||
<div className="text-sm pb-2 font-semibold">
|
||||
Picture descriptions
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Adds captions for images. Ingest is more expensive when enabled.
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={currentSettings.pictureDescriptions}
|
||||
onCheckedChange={checked =>
|
||||
handleSettingsChange({ pictureDescriptions: checked })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 items-center justify-between">
|
||||
<div>
|
||||
<div className="text-sm font-semibold pb-2">OCR</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Extracts text from images/PDFs. Ingest is slower when enabled.
|
||||
<div className="text-sm font-semibold pb-2 flex items-center">
|
||||
Embedding model
|
||||
<Info className="w-3.5 h-3.5 text-muted-foreground ml-2" />
|
||||
</div>
|
||||
<Input
|
||||
disabled
|
||||
value={currentSettings.embeddingModel}
|
||||
onChange={e =>
|
||||
handleSettingsChange({ embeddingModel: e.target.value })
|
||||
}
|
||||
placeholder="text-embedding-3-small"
|
||||
/>
|
||||
</div>
|
||||
<Switch />
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 items-center justify-between">
|
||||
<div>
|
||||
<div className="text-sm pb-2 font-semibold">
|
||||
Picture descriptions
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Adds captions for images. Ingest is more expensive when enabled.
|
||||
</div>
|
||||
</div>
|
||||
<Switch />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-sm font-semibold pb-2 flex items-center">
|
||||
Embedding model
|
||||
<Info className="w-3.5 h-3.5 text-muted-foreground ml-2" />
|
||||
</div>
|
||||
<Input value="text-embedding-3-small" disabled />
|
||||
</div>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
);
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ export interface UnifiedCloudPickerProps {
|
|||
// OneDrive/SharePoint specific props
|
||||
clientId?: string;
|
||||
baseUrl?: string;
|
||||
// Ingest settings
|
||||
onSettingsChange?: (settings: IngestSettings) => void;
|
||||
}
|
||||
|
||||
export interface GoogleAPI {
|
||||
|
|
@ -94,3 +96,11 @@ export interface GooglePickerBuilder {
|
|||
export interface GooglePicker {
|
||||
setVisible: (visible: boolean) => void;
|
||||
}
|
||||
|
||||
export interface IngestSettings {
|
||||
chunkSize: number;
|
||||
chunkOverlap: number;
|
||||
ocr: boolean;
|
||||
pictureDescriptions: boolean;
|
||||
embeddingModel: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { UnifiedCloudPickerProps, CloudFile } from "./types";
|
||||
import {
|
||||
UnifiedCloudPickerProps,
|
||||
CloudFile,
|
||||
IngestSettings as IngestSettingsType,
|
||||
} from "./types";
|
||||
import { PickerHeader } from "./picker-header";
|
||||
import { FileList } from "./file-list";
|
||||
import { IngestSettings } from "./ingest-settings";
|
||||
|
|
@ -16,6 +20,7 @@ export const UnifiedCloudPicker = ({
|
|||
onPickerStateChange,
|
||||
clientId,
|
||||
baseUrl,
|
||||
onSettingsChange,
|
||||
}: UnifiedCloudPickerProps) => {
|
||||
const [isPickerLoaded, setIsPickerLoaded] = useState(false);
|
||||
const [isPickerOpen, setIsPickerOpen] = useState(false);
|
||||
|
|
@ -23,6 +28,21 @@ export const UnifiedCloudPicker = ({
|
|||
const [isLoadingBaseUrl, setIsLoadingBaseUrl] = useState(false);
|
||||
const [autoBaseUrl, setAutoBaseUrl] = useState<string | undefined>(undefined);
|
||||
|
||||
// Settings state with defaults
|
||||
const [ingestSettings, setIngestSettings] = useState<IngestSettingsType>({
|
||||
chunkSize: 1000,
|
||||
chunkOverlap: 200,
|
||||
ocr: false,
|
||||
pictureDescriptions: false,
|
||||
embeddingModel: "text-embedding-3-small",
|
||||
});
|
||||
|
||||
// Handle settings changes and notify parent
|
||||
const handleSettingsChange = (newSettings: IngestSettingsType) => {
|
||||
setIngestSettings(newSettings);
|
||||
onSettingsChange?.(newSettings);
|
||||
};
|
||||
|
||||
const effectiveBaseUrl = baseUrl || autoBaseUrl;
|
||||
|
||||
// Auto-detect base URL for OneDrive personal accounts
|
||||
|
|
@ -167,6 +187,8 @@ export const UnifiedCloudPicker = ({
|
|||
<IngestSettings
|
||||
isOpen={isIngestSettingsOpen}
|
||||
onOpenChange={setIsIngestSettingsOpen}
|
||||
settings={ingestSettings}
|
||||
onSettingsChange={handleSettingsChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue