LanceDB Node.js API 详解:使用 permutationBuilder 构建可复现的训练/测试数据切分流水线
LanceDB Node.js API 详解使用 permutationBuilder 构建可复现的训练/测试数据切分流水线【免费下载链接】lancedbDeveloper-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.项目地址: https://gitcode.com/gh_mirrors/la/lancedb导读permutationBuilder()是 LanceDB JavaScript SDK 中用于创建数据排列Permutation的入口函数它以一张已存在的表为数据源通过链式配置完成过滤filter、切分split与打乱shuffle最终生成一张轻量的排列表用于机器学习训练集/验证集/测试集的划分与数据加载。读完本文你将掌握permutationBuilder的完整用法、五种切分策略随机、哈希、顺序、计算表达式与默认单分片、可复现的随机种子机制以及其底层 Rust 实现原理。函数签名与基本概念在lancedb/lancedb的全局命名空间中permutationBuilder的定义如下见 函数文档function permutationBuilder(table): PermutationBuilder参数tableTable类型即要生成排列的源表返回值PermutationBuilder实例可通过链式方法继续配置。函数文档中给出的经典用法示例const builder permutationBuilder(sourceTable, training_data) .splitRandom({ ratios: [0.8, 0.2], seed: 42 }) .shuffle({ seed: 123 }); const trainingTable await builder.execute();注意对照当前仓库源码 permutation.tspermutationBuilder的实际实现只接收一个参数table: Table文档示例中的第二个字符串参数表名在现行版本中已由.persist(connection, tableName)方法替代。以下内容均以当前源码为准。什么是排列表Permutation Table从 Rust 核心层看排列表是对已有表的一种排列视图见模块文档 permutation.rsA permutation view can apply a filter, divide the data into splits, and shuffle the data. The permutation table only stores the split ids and row ids. It is not a materialized copy of the underlying data and can be very lightweight.即排列表只保存row_id和split_id两列不是底层数据的物化副本因此非常轻量。构建排列表是 O(N) 操作N 为源表行数即使面对数十亿行数据也足够高效省内存。这个结论有单元测试直接印证——builder.rs 中的测试 断言排列表的 schema 字段名恰好为[row_id, split_id]。快速上手构建你的第一个排列表在本地环境中先连接数据库并创建源表然后构造排列表import { connect, permutationBuilder, makeArrowTable } from lancedb/lancedb; const db await connect(./data); const data makeArrowTable( [ { id: 1, value: 10 }, { id: 2, value: 20 }, // ...更多行 ], { vectorColumns: {} }, ); const sourceTable await db.createTable(test_table, data); // 基础排列不切分、不打乱只生成 row_id split_id const builder permutationBuilder(sourceTable); const permutationTable await builder.execute(); console.log(await permutationTable.countRows()); // 10对应测试见 permutation.test.ts其中execute()返回的permutationTable可直接用countRows()统计行数也可传入 SQL 谓词统计特定分片例如countRows(split_id 0)。链式配置方法与参数详解PermutationBuilder类见 permutation.ts 与 类文档提供以下方法所有方法都返回新的PermutationBuilder实例支持连续调用。execute()执行并创建目标表execute(): PromiseTable执行排列并创建目标表。返回 Promise 解析为新的Table实例。注意 builder 是一次性消费的从 NAPI 层源码 permutation.rs 可以看到execute()会通过take()取出内部 builder 状态若再次调用会抛出Builder already consumed错误。const permutationTable await builder.execute(); console.log(Created table: ${permutationTable.name});filter()SQL 过滤filter(filter: string): PermutationBuilder配置过滤条件只有匹配的行才会进入排列表。底层调用with_filterpermutation.rs在 Rust 核心层通过query().only_if(filter)完成扫描过滤builder.rs。builder.filter(age 18 AND status active);persist()持久化排列表persist(connection: Connection, tableName: string): PermutationBuilder默认情况下排列表保存在内存中的临时数据库memory:///表名为permutation见 builder.rs。调用persist后排列表会被写入指定连接对应的数据库作为永久表存在便于后续 DataLoader 工作进程按名字重新打开。builder.persist(connection, permutation_table);splitRandom()随机切分splitRandom(options: SplitRandomOptions): PermutationBuilder按随机方式将行分配到各分片最常用于 train/test 切分。选项接口见 SplitRandomOptions字段如下字段类型说明ratiosnumber[]可选各分片的比例如[0.7, 0.3]countsnumber[]可选各分片的精确行数如[1000, 500]fixednumber可选固定大小第一分片取 N 行其余进入第二分片seednumber可选随机种子保证结果可复现clumpSizenumber可选按连续行块打乱/分配改善云端 I/O 性能splitNamesstring[]可选分片名称存储在排列表的配置元数据中三种切分方式示例// 按比例切分 builder.splitRandom({ ratios: [0.7, 0.3], seed: 42 }); // 按精确行数切分 builder.splitRandom({ counts: [1000, 500], seed: 42 }); // 固定大小切分前 100 行为 split 0其余为 split 1 builder.splitRandom({ fixed: 100, seed: 42 });校验规则NAPI 层强制要求ratios、counts、fixed三者中恰好提供一项否则抛出Exactly one of ratios, counts, or fixed must be providedpermutation.rs并映射为 Rust 核心的SplitSizes::Percentages / Counts / Fixed枚举split.rs。splitHash()哈希切分防数据泄漏splitHash(options: SplitHashOptions): PermutationBuilder基于指定列的哈希值将行分配到分片保证同一实体如 user_id永远落入同一分片这对避免训练/测试数据泄漏至关重要。选项见 SplitHashOptions字段类型说明columnsstring[]必填参与哈希的列名splitWeightsnumber[]必填各分片的哈希空间权重决定分片大致行数比例discardWeightnumber可选丢弃权重控制被剔除行的比例默认 0splitNamesstring[]可选分片名称builder.splitHash({ columns: [user_id], splitWeights: [70, 30], discardWeight: 0, });从 Rust 核心的注释split.rs可以理解权重语义split_weights决定如何划分 u64 哈希空间以近似控制各分片行数但不保证精确比例例如所有行哈希值相同则全部落入同一分片。discard_weight用于丢弃一部分行——比如想要分片 1 约占 5%、分片 2 约占 10% 时可设splitWeights: [1, 2]、discardWeight: 17。校验规则要求columns与splitWeights非空且权重必须大于 0split.rs。splitSequential()顺序切分splitSequential(options: SplitSequentialOptions): PermutationBuilder按行序切分前 N1 行进分片 0接下来 N2 行进分片 1依此类推主要用于调试和测试split.rs。选项见 SplitSequentialOptions支持ratios/counts/fixed/splitNames同样要求三者恰好提供一项。// 按比例 builder.splitSequential({ ratios: [0.8, 0.2] }); // 按行数 builder.splitSequential({ counts: [800, 200] }); // 固定大小 builder.splitSequential({ fixed: 1000 });splitCalculated()基于计算表达式切分splitCalculated(options: SplitCalculatedOptions): PermutationBuilder当数据集中已经存在切分字段如已有split列时直接用一个返回整数0 到分片数减 1的 SQL 计算表达式来分配分片此时counts/ratios会被忽略split.rs。选项见 SplitCalculatedOptions字段类型说明calculationstring必填返回分片编号0 起的 SQL 表达式splitNamesstring[]可选分片名称builder.splitCalculated({ calculation: user_id % 3 });shuffle()打乱行序shuffle(options: ShuffleOptions): PermutationBuilder对排列结果做随机打乱对随机梯度下降等训练场景尤为重要。选项见 ShuffleOptions字段类型说明seednumber可选随机种子使打乱可复现clumpSizenumber可选以连续行块为单位打乱牺牲部分随机性换取 I/O 性能// 基础打乱 builder.shuffle({ seed: 42 }); // 按 clump 打乱 builder.shuffle({ seed: 42, clumpSize: 10 });关于clumpSize的取舍Rust 核心有明确说明builder.rs例如clumpSize: 16意味着按 16 行连续块打乱IOPS 可减少约 16 倍但这 16 行在训练时始终相邻可能影响模型训练效果读取时的局部 shuffle 无法替代全局 shuffle。若不配置 shuffle默认策略为None不排序便于调试。排列表的元数据与版本一致性生成的排列表 schema 元数据中会记录构建时的基表信息builder.rsbase_version排列基于的基表版本号必写base_branch基表所在分支仅非 main 分支时写入main 分支缺省该键split_names分片名称的 JSON 序列化仅在配置了splitNames时写入。这些信息保证 DataLoader 工作进程在基表后续被写入后仍能按记录的快照版本解析 row 地址。从源码注释可以推断build()流程还会为远程表固定快照版本snapshot_at_current_version、拒绝带 LSM 写规格的表未刷盘的行没有 row_id无法被排列引用直接报the data loader does not support tables with an LSM write spec错误、在扫描顺序不确定时按row_id排序以保证分片分配的确定性builder.rs。底层实现Rust 到 JavaScript 的调用链理解完整调用链有助于排查问题JS 层permutationBuilder(table)从LocalTable包装对象中取出内部原生表调用原生模块的nativePermutationBuilder再包成 TS 的PermutationBuilderpermutation.tsNAPI 层permutation_builder从 RustTable克隆内部句柄创建LancePermutationBuilder::new(inner_table)permutation.rs各方法通过modify()函数式更新配置builder 被消费后再次使用会报错核心层build()依次执行——固定快照 → 校验 LSM 写规格 → 按row_id投影 过滤 →Splitter::apply分配分片 →Shuffler::shuffle打乱外部排序默认单文件上限10 * 1024 * 1024行→ 按split_id排序 → 重命名_rowid为row_id→ 写入目标数据库builder.rs。此外排序过程中内存上限可通过环境变量LANCEDB_PERM_BUILDER_MEMORY_LIMIT调整默认值为 100 MiBDEFAULT_MEMORY_LIMITbuilder.rs。典型应用场景训练/验证/测试切分splitRandom({ ratios: [0.8, 0.1, 0.1], seed: 42 })配合.shuffle({ seed: 123 })生成固定随机种子下的可复现划分防泄漏的按实体切分多用户数据使用splitHash({ columns: [user_id], splitWeights: [80, 20] })确保同一用户的行不会同时出现在训练与测试集利用已有切分字段数据集已带split列时用splitCalculated({ calculation: split })直接复用仅取子集通过splitRandom({ ratios: [0.1] })或filter()快速构建 10% 数据的小型排列用于快速实验分布式数据加载排列表是轻量的row_id split_id映射可持久化后供多进程、多节点并行读取同一分片分片并非并行处理的前提单个分片同样可被并行加载。总结permutationBuilder将过滤—切分—打乱这一 ML 数据准备的核心流水线封装为一次链式调用它不复制底层数据只产出轻量的row_id split_id排列表并通过seed保证可复现性。结合 permutation.test.ts、permutation.ts 与 Rust 核心 builder.rs开发者可以快速上手并将其集成到自己的训练数据加载流程中。【免费下载链接】lancedbDeveloper-friendly OSS embedded retrieval library for multimodal AI. Search More; Manage Less.项目地址: https://gitcode.com/gh_mirrors/la/lancedb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考