refactor: improve seed source handling with additional type support, enhanced parsing logic, and text chunking optimization
This commit is contained in:
parent
19ec27c4d7
commit
af00aeb9e4
8 changed files with 98 additions and 32 deletions
|
|
@ -33,6 +33,7 @@ import {
|
|||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/components/ui/tabs";
|
||||
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
|
||||
import mammoth from "mammoth";
|
||||
import { type ReactElement, useEffect, useMemo, useState } from "react";
|
||||
import { extractText, getDocumentProxy } from "unpdf";
|
||||
|
|
@ -60,6 +61,10 @@ const UNSTRUCTURED_ACCEPT = ".txt,.pdf,.docx";
|
|||
const MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
|
||||
const CHUNK_SIZE = 1200;
|
||||
const CHUNK_OVERLAP = 200;
|
||||
const UNSTRUCTURED_SPLITTER = new RecursiveCharacterTextSplitter({
|
||||
chunkSize: CHUNK_SIZE,
|
||||
chunkOverlap: CHUNK_OVERLAP,
|
||||
});
|
||||
|
||||
type SeedDialogProps = {
|
||||
config: SeedConfig;
|
||||
|
|
@ -84,20 +89,12 @@ function stringifyCell(value: unknown): string {
|
|||
}
|
||||
}
|
||||
|
||||
function chunkText(input: string): string[] {
|
||||
async function chunkText(input: string): Promise<string[]> {
|
||||
const text = input.replace(/\r\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
||||
if (!text) return [];
|
||||
|
||||
const chunks: string[] = [];
|
||||
let cursor = 0;
|
||||
const overlap = Math.max(0, Math.min(CHUNK_OVERLAP, CHUNK_SIZE - 1));
|
||||
while (cursor < text.length) {
|
||||
const end = Math.min(cursor + CHUNK_SIZE, text.length);
|
||||
chunks.push(text.slice(cursor, end).trim());
|
||||
if (end >= text.length) break;
|
||||
cursor = Math.max(0, end - overlap);
|
||||
}
|
||||
return chunks.filter(Boolean);
|
||||
const chunks = await UNSTRUCTURED_SPLITTER.splitText(text);
|
||||
return chunks.map((chunk) => chunk.trim()).filter(Boolean);
|
||||
}
|
||||
|
||||
async function fileToBase64Payload(file: File): Promise<string> {
|
||||
|
|
@ -218,7 +215,7 @@ export function SeedDialog({ config, onUpdate }: SeedDialogProps): ReactElement
|
|||
}
|
||||
|
||||
const text = await extractUnstructuredText(unstructuredFile);
|
||||
const chunks = chunkText(text);
|
||||
const chunks = await chunkText(text);
|
||||
if (chunks.length === 0) {
|
||||
throw new Error("No text found in file.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,12 +300,12 @@ export const useRecipeStudioStore = create<RecipeStudioState>((set, get) => ({
|
|||
if (!existing) {
|
||||
return buildAddedNodeState(state, "seed", type);
|
||||
}
|
||||
const nextSourceType: SeedSourceType =
|
||||
type === "seed_local"
|
||||
? "local"
|
||||
: type === "seed_unstructured"
|
||||
? "unstructured"
|
||||
: "hf";
|
||||
let nextSourceType: SeedSourceType = "hf";
|
||||
if (type === "seed_local") {
|
||||
nextSourceType = "local";
|
||||
} else if (type === "seed_unstructured") {
|
||||
nextSourceType = "unstructured";
|
||||
}
|
||||
|
||||
const nextConfig = {
|
||||
...existing,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import type {
|
|||
LlmToolConfig,
|
||||
NodeConfig,
|
||||
RecipeProcessorConfig,
|
||||
SeedSourceType,
|
||||
} from "../../types";
|
||||
import { buildEdges } from "./edges";
|
||||
import { isRecord, parseJson, readString } from "./helpers";
|
||||
|
|
@ -29,6 +30,7 @@ type RecipeInput = {
|
|||
type UiInput = {
|
||||
nodes?: unknown;
|
||||
edges?: unknown;
|
||||
seed_source_type?: unknown;
|
||||
};
|
||||
|
||||
function parseProcessors(input: unknown): RecipeProcessorConfig[] {
|
||||
|
|
@ -219,11 +221,18 @@ export function importRecipePayload(input: string): ImportResult {
|
|||
const nameToId = new Map<string, string>();
|
||||
|
||||
let nextId = 1;
|
||||
const uiSeedSourceTypeRaw = readString(ui?.seed_source_type);
|
||||
const uiSeedSourceType: SeedSourceType | undefined =
|
||||
uiSeedSourceTypeRaw === "hf" ||
|
||||
uiSeedSourceTypeRaw === "local" ||
|
||||
uiSeedSourceTypeRaw === "unstructured"
|
||||
? uiSeedSourceTypeRaw
|
||||
: undefined;
|
||||
|
||||
if (recipe.seed_config) {
|
||||
const id = `n${nextId}`;
|
||||
nextId += 1;
|
||||
const seedConfig = parseSeedConfig(recipe.seed_config, id);
|
||||
const seedConfig = parseSeedConfig(recipe.seed_config, id, uiSeedSourceType);
|
||||
if (seedConfig) {
|
||||
configs.push(seedConfig);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ function parseSeedSettings(seedConfigRaw: unknown): Partial<SeedConfig> {
|
|||
let hf_endpoint = "https://huggingface.co";
|
||||
let hf_repo_id = "";
|
||||
let local_file_name = "";
|
||||
let unstructured_file_name = "";
|
||||
const unstructured_file_name = "";
|
||||
const sourceRaw = seedConfigRaw.source;
|
||||
if (isRecord(sourceRaw)) {
|
||||
const seedType = readString(sourceRaw.seed_type);
|
||||
|
|
@ -127,12 +127,23 @@ function parseSeedSettings(seedConfigRaw: unknown): Partial<SeedConfig> {
|
|||
export function parseSeedConfig(
|
||||
seedConfigRaw: unknown,
|
||||
id: string,
|
||||
preferredSourceType?: SeedSourceType,
|
||||
): SeedConfig | null {
|
||||
if (!seedConfigRaw) {
|
||||
return null;
|
||||
}
|
||||
const parsed = parseSeedSettings(seedConfigRaw);
|
||||
let sourceType: SeedSourceType = "hf";
|
||||
if (parsed.seed_source_type === "hf") {
|
||||
sourceType = "hf";
|
||||
} else if (preferredSourceType) {
|
||||
sourceType = preferredSourceType;
|
||||
} else if (parsed.seed_source_type) {
|
||||
sourceType = parsed.seed_source_type;
|
||||
}
|
||||
return {
|
||||
...makeDefaultSeedConfig(id),
|
||||
...parseSeedSettings(seedConfigRaw), // payload-only fields override ui defaults
|
||||
...parsed, // payload-only fields override ui defaults
|
||||
seed_source_type: sourceType,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ export function buildRecipePayload(
|
|||
ui: {
|
||||
nodes: uiNodes,
|
||||
edges: uiEdges,
|
||||
...(firstSeed && { seed_source_type: firstSeed.seed_source_type }),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ export type RecipePayload = {
|
|||
ui: {
|
||||
nodes: { id: string; x: number; y: number }[];
|
||||
edges: { from: string; to: string; type?: string }[];
|
||||
// ui-only, used to preserve seed block mode across imports/refresh
|
||||
seed_source_type?: "hf" | "local" | "unstructured";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue