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:
Deon Sanchez 2025-09-19 09:26:12 -06:00
parent ce34c8ab0f
commit e9de598a0f
4 changed files with 157 additions and 57 deletions

View file

@ -5,6 +5,7 @@ import { useParams, useRouter } from "next/navigation";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { ArrowLeft, AlertCircle } from "lucide-react"; import { ArrowLeft, AlertCircle } from "lucide-react";
import { UnifiedCloudPicker, CloudFile } from "@/components/cloud-picker"; import { UnifiedCloudPicker, CloudFile } from "@/components/cloud-picker";
import type { IngestSettings } from "@/components/cloud-picker/types";
import { useTask } from "@/contexts/task-context"; import { useTask } from "@/contexts/task-context";
import { Toast } from "@/components/ui/toast"; import { Toast } from "@/components/ui/toast";
@ -38,6 +39,13 @@ export default function UploadProviderPage() {
null null
); );
const [showSuccessToast, setShowSuccessToast] = useState(false); const [showSuccessToast, setShowSuccessToast] = useState(false);
const [ingestSettings, setIngestSettings] = useState<IngestSettings>({
chunkSize: 1000,
chunkOverlap: 200,
ocr: false,
pictureDescriptions: false,
embeddingModel: "text-embedding-3-small",
});
useEffect(() => { useEffect(() => {
const fetchConnectorInfo = async () => { const fetchConnectorInfo = async () => {
@ -167,9 +175,11 @@ export default function UploadProviderPage() {
connection_id: string; connection_id: string;
max_files?: number; max_files?: number;
selected_files?: string[]; selected_files?: string[];
settings?: IngestSettings;
} = { } = {
connection_id: connector.connectionId, connection_id: connector.connectionId,
selected_files: selectedFiles.map(file => file.id), selected_files: selectedFiles.map(file => file.id),
settings: ingestSettings,
}; };
const response = await fetch(`/api/connectors/${connector.type}/sync`, { const response = await fetch(`/api/connectors/${connector.type}/sync`, {
@ -337,6 +347,7 @@ export default function UploadProviderPage() {
isAuthenticated={true} isAuthenticated={true}
accessToken={accessToken || undefined} accessToken={accessToken || undefined}
clientId={connector.clientId} clientId={connector.clientId}
onSettingsChange={setIngestSettings}
/> />
</div> </div>

View file

@ -8,16 +8,39 @@ import {
CollapsibleTrigger, CollapsibleTrigger,
} from "@/components/ui/collapsible"; } from "@/components/ui/collapsible";
import { ChevronRight, Info } from "lucide-react"; import { ChevronRight, Info } from "lucide-react";
import { IngestSettings as IngestSettingsType } from "./types";
interface IngestSettingsProps { interface IngestSettingsProps {
isOpen: boolean; isOpen: boolean;
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
settings?: IngestSettingsType;
onSettingsChange?: (settings: IngestSettingsType) => void;
} }
export const IngestSettings = ({ export const IngestSettings = ({
isOpen, isOpen,
onOpenChange, onOpenChange,
}: IngestSettingsProps) => ( settings,
onSettingsChange,
}: IngestSettingsProps) => {
// Default settings
const defaultSettings: IngestSettingsType = {
chunkSize: 1000,
chunkOverlap: 200,
ocr: false,
pictureDescriptions: false,
embeddingModel: "text-embedding-3-small",
};
// Use provided settings or defaults
const currentSettings = settings || defaultSettings;
const handleSettingsChange = (newSettings: Partial<IngestSettingsType>) => {
const updatedSettings = { ...currentSettings, ...newSettings };
onSettingsChange?.(updatedSettings);
};
return (
<Collapsible <Collapsible
open={isOpen} open={isOpen}
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
@ -39,11 +62,27 @@ export const IngestSettings = ({
<div className="flex items-center gap-4 w-full"> <div className="flex items-center gap-4 w-full">
<div className="w-full"> <div className="w-full">
<div className="text-sm mb-2 font-semibold">Chunk size</div> <div className="text-sm mb-2 font-semibold">Chunk size</div>
<Input type="number" /> <Input
type="number"
value={currentSettings.chunkSize}
onChange={e =>
handleSettingsChange({
chunkSize: parseInt(e.target.value) || 0,
})
}
/>
</div> </div>
<div className="w-full"> <div className="w-full">
<div className="text-sm mb-2 font-semibold">Chunk overlap</div> <div className="text-sm mb-2 font-semibold">Chunk overlap</div>
<Input type="number" /> <Input
type="number"
value={currentSettings.chunkOverlap}
onChange={e =>
handleSettingsChange({
chunkOverlap: parseInt(e.target.value) || 0,
})
}
/>
</div> </div>
</div> </div>
@ -54,7 +93,12 @@ export const IngestSettings = ({
Extracts text from images/PDFs. Ingest is slower when enabled. Extracts text from images/PDFs. Ingest is slower when enabled.
</div> </div>
</div> </div>
<Switch /> <Switch
checked={currentSettings.ocr}
onCheckedChange={checked =>
handleSettingsChange({ ocr: checked })
}
/>
</div> </div>
<div className="flex gap-2 items-center justify-between"> <div className="flex gap-2 items-center justify-between">
@ -66,7 +110,12 @@ export const IngestSettings = ({
Adds captions for images. Ingest is more expensive when enabled. Adds captions for images. Ingest is more expensive when enabled.
</div> </div>
</div> </div>
<Switch /> <Switch
checked={currentSettings.pictureDescriptions}
onCheckedChange={checked =>
handleSettingsChange({ pictureDescriptions: checked })
}
/>
</div> </div>
<div> <div>
@ -74,9 +123,17 @@ export const IngestSettings = ({
Embedding model Embedding model
<Info className="w-3.5 h-3.5 text-muted-foreground ml-2" /> <Info className="w-3.5 h-3.5 text-muted-foreground ml-2" />
</div> </div>
<Input value="text-embedding-3-small" disabled /> <Input
disabled
value={currentSettings.embeddingModel}
onChange={e =>
handleSettingsChange({ embeddingModel: e.target.value })
}
placeholder="text-embedding-3-small"
/>
</div> </div>
</div> </div>
</CollapsibleContent> </CollapsibleContent>
</Collapsible> </Collapsible>
); );
};

View file

@ -23,6 +23,8 @@ export interface UnifiedCloudPickerProps {
// OneDrive/SharePoint specific props // OneDrive/SharePoint specific props
clientId?: string; clientId?: string;
baseUrl?: string; baseUrl?: string;
// Ingest settings
onSettingsChange?: (settings: IngestSettings) => void;
} }
export interface GoogleAPI { export interface GoogleAPI {
@ -94,3 +96,11 @@ export interface GooglePickerBuilder {
export interface GooglePicker { export interface GooglePicker {
setVisible: (visible: boolean) => void; setVisible: (visible: boolean) => void;
} }
export interface IngestSettings {
chunkSize: number;
chunkOverlap: number;
ocr: boolean;
pictureDescriptions: boolean;
embeddingModel: string;
}

View file

@ -1,7 +1,11 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { UnifiedCloudPickerProps, CloudFile } from "./types"; import {
UnifiedCloudPickerProps,
CloudFile,
IngestSettings as IngestSettingsType,
} from "./types";
import { PickerHeader } from "./picker-header"; import { PickerHeader } from "./picker-header";
import { FileList } from "./file-list"; import { FileList } from "./file-list";
import { IngestSettings } from "./ingest-settings"; import { IngestSettings } from "./ingest-settings";
@ -16,6 +20,7 @@ export const UnifiedCloudPicker = ({
onPickerStateChange, onPickerStateChange,
clientId, clientId,
baseUrl, baseUrl,
onSettingsChange,
}: UnifiedCloudPickerProps) => { }: UnifiedCloudPickerProps) => {
const [isPickerLoaded, setIsPickerLoaded] = useState(false); const [isPickerLoaded, setIsPickerLoaded] = useState(false);
const [isPickerOpen, setIsPickerOpen] = useState(false); const [isPickerOpen, setIsPickerOpen] = useState(false);
@ -23,6 +28,21 @@ export const UnifiedCloudPicker = ({
const [isLoadingBaseUrl, setIsLoadingBaseUrl] = useState(false); const [isLoadingBaseUrl, setIsLoadingBaseUrl] = useState(false);
const [autoBaseUrl, setAutoBaseUrl] = useState<string | undefined>(undefined); 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; const effectiveBaseUrl = baseUrl || autoBaseUrl;
// Auto-detect base URL for OneDrive personal accounts // Auto-detect base URL for OneDrive personal accounts
@ -167,6 +187,8 @@ export const UnifiedCloudPicker = ({
<IngestSettings <IngestSettings
isOpen={isIngestSettingsOpen} isOpen={isIngestSettingsOpen}
onOpenChange={setIsIngestSettingsOpen} onOpenChange={setIsIngestSettingsOpen}
settings={ingestSettings}
onSettingsChange={handleSettingsChange}
/> />
</div> </div>
); );