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 { 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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,75 +8,132 @@ 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,
|
||||||
<Collapsible
|
onSettingsChange,
|
||||||
open={isOpen}
|
}: IngestSettingsProps) => {
|
||||||
onOpenChange={onOpenChange}
|
// Default settings
|
||||||
className="border rounded-md p-4 border-muted-foreground/20"
|
const defaultSettings: IngestSettingsType = {
|
||||||
>
|
chunkSize: 1000,
|
||||||
<CollapsibleTrigger className="flex items-center gap-2 justify-between w-full -m-4 p-4 rounded-md transition-colors">
|
chunkOverlap: 200,
|
||||||
<div className="flex items-center gap-2">
|
ocr: false,
|
||||||
<ChevronRight
|
pictureDescriptions: false,
|
||||||
className={`h-4 w-4 text-muted-foreground transition-transform duration-200 ${
|
embeddingModel: "text-embedding-3-small",
|
||||||
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">
|
// Use provided settings or defaults
|
||||||
<div className="pt-5 space-y-5">
|
const currentSettings = settings || defaultSettings;
|
||||||
<div className="flex items-center gap-4 w-full">
|
|
||||||
<div className="w-full">
|
const handleSettingsChange = (newSettings: Partial<IngestSettingsType>) => {
|
||||||
<div className="text-sm mb-2 font-semibold">Chunk size</div>
|
const updatedSettings = { ...currentSettings, ...newSettings };
|
||||||
<Input type="number" />
|
onSettingsChange?.(updatedSettings);
|
||||||
</div>
|
};
|
||||||
<div className="w-full">
|
|
||||||
<div className="text-sm mb-2 font-semibold">Chunk overlap</div>
|
return (
|
||||||
<Input type="number" />
|
<Collapsible
|
||||||
</div>
|
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>
|
</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>
|
||||||
<div className="text-sm font-semibold pb-2">OCR</div>
|
<div className="text-sm font-semibold pb-2 flex items-center">
|
||||||
<div className="text-sm text-muted-foreground">
|
Embedding model
|
||||||
Extracts text from images/PDFs. Ingest is slower when enabled.
|
<Info className="w-3.5 h-3.5 text-muted-foreground ml-2" />
|
||||||
</div>
|
</div>
|
||||||
|
<Input
|
||||||
|
disabled
|
||||||
|
value={currentSettings.embeddingModel}
|
||||||
|
onChange={e =>
|
||||||
|
handleSettingsChange({ embeddingModel: e.target.value })
|
||||||
|
}
|
||||||
|
placeholder="text-embedding-3-small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Switch />
|
|
||||||
</div>
|
</div>
|
||||||
|
</CollapsibleContent>
|
||||||
<div className="flex gap-2 items-center justify-between">
|
</Collapsible>
|
||||||
<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>
|
|
||||||
);
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue