Faiss contrib 模块深度解析:从分布式索引、磁盘合并到 PyTorch 互操作的 Python 辅助库
faiss 的 contrib/ 目录是一组随 Python 包一起编译为 faiss.contrib 模块的辅助工具库,覆盖分布式检索、磁盘索引合并、超大规模暴力搜索、PyTorch 张量互操作、IVF 索引高级操控等场景。本文基于仓库内的 contrib/README.md 逐模块展开,并结合各模块源码实现与测试用例,说明每个模块的定位、关键 API 与底层工作方式,帮助你在索引放不下内存、需要跨机器分片或与 PyTorch 工作流集成时,直接复用这些经过验证的工具。
1. contrib 的编译方式与依赖模型
从 contrib/README.md 的 "Code structure" 一节可以确认两条基本规则:
- 编译产物:整个
contrib目录会被编译进 Python 包的faiss.contrib模块,因此导入方式为from faiss.contrib import client_server这类形式,仓库中的测试文件 tests/test_contrib.py 第 18–34 行展示了这种用法(直接导入big_batch_search、clustering、datasets、evaluation、factory_tools、inspect_tools、ivf_tools及ondisk.merge_ondisk等符号)。 - 可选依赖不自带:部分模块依赖 GPU 版 faiss、PyTorch、h5py 等外部库,这些依赖不会被编译进包里,需要用户自行提供。也就是说:在没有安装 GPU 版的普通 CPU 环境里,
faiss.contrib仍然可以导入,只是涉及 GPU 的分支不可用;同理 contrib/clustering.py 第 16–19 行对scipy.sparse的导入做了 try/except 降级处理,缺失 scipy 时仅提示 "Python k-means will not work" 而不中断导入。
这种设计让 contrib 保持了"低耦合、按需提供"的特性:核心 faiss 包不因此膨胀,高级功能按需启用。
2. 模块总览
| 模块 | 职责 | 典型使用场景 |
|---|---|---|
| rpc.py | 极简 pickle 序列化 RPC 框架 | 作为 client_server 的通信底座 |
| client_server.py | 将 faiss 索引暴露为远程服务,客户端合并多机结果 | 数据集跨机器分片的分布式检索 |
| ondisk.py | 将多个内存索引分片合并写入一个磁盘倒排索引 | 超大规模 IVF 索引落盘 |
| exhaustive_search.py | 分块计算 ground truth(支持 GPU) | 召回率评测、超大库精确 KNN |
| torch_utils.py | 让 PyTorch 张量可直接作为 faiss 参数 | 深度学习 + 向量检索混合流水线 |
| inspect_tools.py | 读取 SWIG 包装的 C++ 对象内部字段 | 检查倒排列表、PQ 码本、变换矩阵 |
| ivf_tools.py | 覆盖/扩展 IVF 粗量化与指定列表搜索 | 自定义分配策略、重排倒排列表 |
| datasets.py | 标准数据集的统一访问接口(可能依赖 h5py) | 下载/读取 sift1M、bigann、deep 等 |
| factory_tools.py | 解析与反推 index_factory 字符串 |
计算编码长度、由索引对象还原字符串 |
| evaluation.py | 检索结果的多种评测函数 | KNN/Range 结果的 Precision-Recall |
| clustering.py | Python 版 kmeans 与两级聚类 | 特殊数据类型聚类、训练 IMI 类索引 |
| big_batch_search.py | 按倒排列表逐桶批量检索 IVF | 大库 + 大批量查询的搜索加速 |
仓库中还存在一个未在 README 列出的 contrib/vecs_io.py,提供 fvecs/bvecs/ivecs 格式的文件读取、内存映射与分块迭代(bvecs_iter、bvecs_iter_chunked 等),datasets.py 中大容量数据集的 mmap 访问正是建立在这些函数之上。
3. rpc.py:pickle 化的极简 RPC
rpc.py 是一个"仅用于演示"的远程过程调用实现,README 中对其的定位是:"函数参数与结果都用 pickle 序列化,供 client_server.py 使用"。源码揭示了它的具体协议与安全设计:
- 传输层:
FileSock类(第 47–87 行)把 socket 包装成支持read/write的文件对象,使 pickle 可以直接在其上序列化,发送时以 512KB 为块循环send。 - 调用协议:客户端发送
(fname, args),服务端执行Server对象的同名方法,回送(st, ret)——st为 None 或执行期异常的 traceback 字符串,ret为返回值。Client.__getattr__(第 233–234 行)使得客户端可以像调用本地方法一样透明地调用远程方法,异常在客户端被重新抛出。 - 安全白名单:
RestrictedUnpickler(第 35–44 行)只允许反序列化numpy与numpy.core.multiarray两个模块的对象,其他一律抛出UnpicklingError。模块 docstring 明确声明:"This code is for demonstration purposes only...not meant to be run on an untrusted network or in a production environment",即不能直接用于不受信任的网络或生产环境。 - 服务入口:
run_server(new_handler, port=PORT, ...),默认端口PORT = 12032,每个连接在新线程中执行exec_loop;report_to_file参数可把"主机:端口"写入文件,便于客户端发现服务。
4. client_server.py:把索引分片到多台机器
client_server.py 是 contrib 中"分布式索引"方案的核心:服务器把请求转发给本地 faiss 索引,客户端把多台机器的子索引结果用堆合并。
4.1 服务端
SearchServer(第 17–34 行)继承 rpc.Server,在构造时通过 faiss.extract_index_ivf(index) 取出内部 IVF 子索引,从而暴露:
set_nprobe(nprobe):远程设置探测半径;get_ntotal():远程查询向量数;__getattr__:其余所有方法透明转发给索引对象本身。
启动入口为 run_index_server(index, port, v6=False)(第 37–39 行),该函数会永久循环地服务请求。
4.2 客户端
ClientIndex 的构造接受 machine_ports: List[Tuple[str, int]](主机、端口对列表),内部为每台机器建立 rpc.Client 连接,并用 ThreadPool 并发下发搜索。其 search(x, k) 的实现要点(第 76–85 行):
def search(self, x, k: int):
rh = faiss.ResultHeap(x.shape[0], k)
for Di, Ii in self.pool.imap(
lambda idx: idx.search(x, k), self.sub_indexes
):
rh.add_result(Di, Ii)
rh.finalize()
return rh.D, rh.I
即:各子索引各自返回 top-k,faiss.ResultHeap 做增量合并,最终 finalize() 得到全局 top-k。此外还提供 set_omp_num_threads、get_ntotal(跨机器求和)等便捷方法。
4.3 端到端示例:demos/demo_client_server_ivf.py
demos/demo_client_server_ivf.py 完整演示了以 SIFT1M 为例的四机分片流程,按命令行参数 stage 分阶段执行:
- stage 0(第 37–44 行):读取
sift_learn.fvecs,用faiss.index_factory(d, "IVF4096,Flat")训练并保存/tmp/trained.index; - stage 1–4(第 47–56 行):把
sift_base.fvecs均分 4 份,每份分别add_with_ids到 trained index 的副本中,写出block_0..3.index(注意用add_with_ids保持全局 ID 连续); - stage 5–8(第 67–76 行):各自读取一个分片,在
localhost的 12010–12013 端口调用run_index_server; - stage 9(第 79–91 行):构造
ClientIndex(machine_ports),执行client_index.set_nprobe(16)与client_index.search(xq, 5),并与sift_groundtruth.ivecs对比输出 recall@1。
这套"训练一次 → 分片写入 → 多进程起服务 → 客户端合并"的模式,正是 README 所链接的 wiki "Distributed index" 方案的参考实现,适合数据集总量超过单机内存的场景。
5. ondisk.py:把多个分片合并成一个磁盘索引
ondisk.py 只提供一个核心函数 merge_ondisk(trained_index, shard_fnames, ivfdata_fname, shift_ids=False)(第 13–64 行),其流程非常值得细读:
- 以 mmap 方式读取分片:对每个
shard_fnames中的索引调用faiss.read_index(fname, faiss.IO_FLAG_MMAP),注释明确说明这样做的目的——"避免真正把数据读进内存,因此倒排列表总大小可以超过可用 RAM"; - 脱离所有权:取出
index_ivf.invlists后设置index_ivf.own_invlists = False,防止倒排列表随索引对象析构而释放; - 构建输出倒排列表:创建
faiss.OnDiskInvertedLists(nlist, code_size, ivfdata_fname),其数据写入ivfdata_fname文件; - 合并:
invlists.merge_from_multiple(ivf_vector.data(), ivf_vector.size(), shift_ids)把所有分片的倒排列表合并,shift_ids控制是否按分片偏移全局 ID; - 替换并移交所有权:
index_ivf.replace_invlists(invlists, True)后调用invlists.this.disown(),让底层 C++ 对象接管生命周期。
两个硬约束在源码中可以直接看到:assert not isinstance(trained_index, faiss.IndexIVFPQR)(IVFPQR 因需要额外元数据而不支持落盘)与 assert index.ntotal == 0("works only on empty index",只能合并进空索引)。这个函数与 demos/demo_client_server_ivf.py 的内存分片方案互补,构成"合并到磁盘"的 On-disk storage 标准路径。
6. exhaustive_search.py:超出内存的精确搜索
exhaustive_search.py 提供在不把整个库载入内存的前提下计算 ground truth 的能力,README 指明其测试位于 tests/test_contrib.TestComputeGT(对应 tests/test_contrib.py 第 37 行起的 TestComputeGT 类)。
6.1 knn_ground_truth:分块 KNN + 堆合并
knn_ground_truth(xq, db_iterator, k, metric_type=faiss.METRIC_L2, shard=False, ngpu=-1)(第 15–53 行)的算法是:
- 用一个只容纳当前块的
faiss.IndexFlat(必要时经faiss.index_cpu_to_all_gpus克隆到全部 GPU,shard选项控制多卡分片)做逐块精确搜索; - 每块搜索后用
I += i0修正全局偏移,再rh.add_result(D, I)进faiss.ResultHeap(keep_max按faiss.is_similarity_metric自动设置以支持内积度量); - 块处理完
index.reset()释放,循环结束后rh.finalize()返回全局 top-k。
测试用例(第 39–59 行)用 10000 个库向量按 1000 一批的迭代器计算 k=10 的 GT,与一次性 IndexFlat.search 的结果比对索引完全相等、距离在 1e-4 内一致。
6.2 GPU 上的范围搜索:range_search_gpu
由于 GPU 索引不原生支持 range search,range_search_gpu(xq, r2, index_gpu, index_cpu, gpu_k=1024)(第 60 行起)采用"KNN 模拟 + CPU 兜底"策略:先在 GPU 上做 k=min(ntotal, gpu_k) 的 KNN;若某个查询的第 k 近邻距离未覆盖阈值(即 D[:, k-1] < r2(L2)或 > r2(相似度)),说明结果可能不全,则把这些查询回落到 index_cpu(可以是支持 range search 的 CPU 索引,或直接是 numpy 矩阵——后者会自动构建 Flat 索引)做精确 range search,最后用 faiss.CombinerRangeKNNfloat/int16(二进制索引)两种查询无遗漏地拼合结果。range_ground_truth(第 159 行起)进一步把该逻辑包装成分块 GT 计算,CPU/GPU 两条路径共用同一套 lims/D/I 输出格式。
6.3 结果数量受控的范围搜索:range_search_max_results
range_search_max_results(index, query_iterator, radius, max_results, min_results, ...)(第 277 行起)面向查询量巨大的场景:它边搜索边统计总结果数,一旦 totres > max_results 就调用 apply_maxres——用 np.partition 在所有已收集距离中快速选出新半径,使结果数回落到 min_results(默认 0.8 * max_results)。exponential_query_iterator(xq, start_bs=32, max_bs=20000)(第 382 行起)则提供"32 → 64 → 128 → …"指数增长的查询分批,让半径在早期小批量上快速收敛,避免中间结果爆炸。
7. torch_utils.py:让 PyTorch 张量直喂 faiss
torch_utils.py 实现 README 所述"导入后 pytorch Tensors(CPU 或 GPU)即可作为 faiss 索引和函数的参数"。其实现机制与约束值得掌握:
7.1 指针桥接
核心是一组 swig_ptr_from_*Tensor 函数(第 36–88 行),它们通过 x.untyped_storage().data_ptr() + x.storage_offset() * 元素大小 拿到张量的真实内存地址,再经 faiss.cast_integer_to_float_ptr 等函数转成 SWIG 指针——这一步等价于 numpy 路径中 faiss.swig_ptr 的作用,且要求张量 is_contiguous()、dtype 严格匹配(float32/float16/bfloat16/int32/int64/uint8)。
7.2 方法猴子补丁
handle_torch_Index(the_class)(第 149 行起)重写了 add、add_with_ids、assign、train、search、search_preassigned、search_and_reconstruct、remove_ids、reconstruct、reconstruct_n、update_vectors、range_search、sa_encode、sa_decode 等方法,并在模块底部(第 649–654 行)遍历 faiss 模块中所有 Index 子类批量应用。每个重写方法遵循统一模式:
- 参数是
np.ndarray→ 转发回 numpy 版本(如self.search_numpy(...)),保证兼容; - 参数是 GPU 张量 → 断言索引本身是 GPU 索引(
hasattr(self, "getDevice")),并在using_stream(self.getResources())上下文内调用*_ex/*_c底层接口; - 参数是 CPU 张量 → 直接调用底层
*_ex/*_c。
7.3 GPU 流同步
using_stream(res, pytorch_stream=None)(第 96–123 行)是互操作的正确性关键:它把 faiss GpuResources 的默认 CUDA 流切换为 torch.cuda.current_stream(),退出时恢复原流。这样 faiss GPU 索引与 PyTorch 计算在同一 CUDA 流中按序执行,无需显式同步,也不会破坏 PyTorch 的异步执行模型——这正是 README 中"自动完成与当前 pytorch 流的同步"的具体实现。
7.4 模块级函数与使用约束
faiss.knn、faiss.knn_gpu、faiss.pairwise_distance_gpu 也被打了同样的补丁:knn 支持 CPU torch 张量(L2/内积/扩展度量分别落到 knn_L2sqr、knn_inner_product、knn_extra_metrics);knn_gpu 支持 float32/float16/bfloat16 查询与库向量,并允许 int64/int32 索引输出,通过 faiss.GpuDistanceParams 一次性传给 faiss.bfKnn。
使用约束(与 README 完全一致):导入后 numpy 数组仍可用,但同一次调用的所有参数必须统一为 numpy 或 torch,禁止混用;torch GPU 张量只能配 faiss GPU 索引。测试覆盖见 tests/torch_test_contrib.py(CPU)与 GPU 侧的 GPU 测试。
8. inspect_tools.py:窥探 SWIG 包装的 C++ 对象
inspect_tools.py 正如 README 所说,"大多只是读取字段并转换为合适的 python 数组"。常用函数:
get_invlist(invlists, l):返回第 l 个倒排列表的(list_ids, list_codes);对普通InvertedLists码长即code_size,对BlockInvertedLists则按(ls_round, bs // npb, npb)形状整形;并通过release_ids/release_codes正确释放 SWIG 临时对象;get_invlist_sizes(invlists):全部列表的规模数组,常用于检查 IVF 桶的均衡性;get_pq_centroids(pq):PQ 码本展开为(M, ksub, dsub)数组;get_LinearTransform_matrix(pca)/make_LinearTransform_matrix(A, b):从 PCA/OPQ/随机旋转等线性变换中提取或注入矩阵 A 与偏置 b,后者会自动set_is_orthonormal(),方便手工构造正交变换;get_flat_data(index)/get_flat_codes(index_flat):从IndexFlat/IndexFlatCodes导出数据矩阵或码字;get_NSG_neighbors(nsg):导出 NSG 图的 N×K 邻居表;print_object_fields(obj):列出 SWIG 已知的所有字段,排障时很实用。
9. ivf_tools.py:IVF 粗量化与指定列表搜索的扩展
ivf_tools.py 提供 README 所称"覆盖 IVF 粗量化器的若干函数,为分配提供额外灵活性":
add_preassigned(index_ivf, x, a, ids=None):分配结果a已算好时,直接经add_core写入倒排列表,跳过量化器计算;search_preassigned(index_ivf, xq, k, list_nos, coarse_dis=None):在用户指定的倒排列表编号list_nos(形状(n, nprobe))上执行搜索。源码注释指出它相对IndexIVF.search_preassigned的优势是支持带 pretransform 的复合索引(链长为 1 时自动先transform.apply(xq)再下探),且对coarse_dis缺省时自动补零矩阵(内积 + 残差编码时该值会真正参与距离计算);range_search_preassigned:同样思想的范围搜索版,经range_search_preassigned_c拿到原始指针后拷贝为 numpy 数组返回;replace_ivf_quantizer(index_ivf, new_quantizer):原子地替换粗量化器——新量化器为空时会自动用原reconstruct_n()得到的质心完成训练并添加;旧量化器通过own_fields交接干净释放,并登记进referenced_objects防悬垂;permute_invlists(index_ivf, perm)与sort_invlists_by_size(index_ivf):按任意置换重排倒排列表并同步quantizer.permute_entries,后者按桶规模升序排列,便于把小桶排在前面以改善尾延迟。
10. datasets.py:标准数据集的统一访问
datasets.py 定义 Dataset 抽象基类(第 23 行起,统一 get_queries/get_database/get_groundtruth/distance 等接口)与一批具体数据集:DatasetSIFT1M、DatasetGIST1M、DatasetBigANN、DatasetDeep1B、DatasetGlove、DatasetMusic100、DatasetDINO10B,以及无需下载的 SyntheticDataset。统一入口是 dataset_from_name(dataset="deep1M", download=False)(第 508–547 行),支持 sift1M、gist1M、bigann1M..1B、deep1M..1B、music-100、glove、dino* 等名称解析;set_dataset_basedir(path)(第 150 行)用于切换数据根目录。
面向超大规模数据的两个设计细节:
DatasetDINO10B.get_database()(第 464–475 行)在库规模超过 1000 万时直接抛出NotImplementedError,提示改用database_iterator或限制规模——避免误把几十 GB 数据mmap后一次取回;database_iterator(bs=10_000)基于 vecs_io.py 的bvecs_iter_chunked顺序读取chunk_XXXX.bvecs分块文件,且自带块序号连续性校验(缺块即报Gap detected);- 小数据集(如 SIFT1M)的查询则通过
bvecs_mmap内存映射读取后经sanitize转换为 float32,几乎零拷贝。
README 提示该模块"may require h5py",即部分数据集路径依赖 h5py,使用前需确认环境已安装。
11. factory_tools.py:factory 字符串的双向解析
factory_tools.py 处理 index_factory 字符串相关的两个高频需求:
11.1 由字符串算编码长度:get_code_size(d, indexkey)
get_code_size(第 10–76 行)对裸 key(去掉 IVF 前缀后)逐一匹配:
PQ(M)x(n)(fs|fsr)?:(M*n+7)//8字节(fast-scan 变体也按字节码计算);SQ8→d、SQ4→(d+1)//2、SQ6→(d*6+7)//8、SQfp16/SQbf16→2d;HNSW(M):约4d + M*2*4字节;IMI、IVF...(…)复合前缀递归拆解;Refine(x)为两段之和;OPQ/PCA/RR前缀替换维度后递归。
这在没有实际构建索引的情况下预估磁盘占用非常有用,且与 faiss.Index.code_size 语义一致。
11.2 由对象反推字符串:reverse_index_factory(index)
reverse_index_factory(第 83 行起)按类型分派还原 factory 字符串:IndexFlat→Flat;IndexIVF 根据量化器类型拼出 IVF{nlist}、IMI{M}x{nbits} 或 IVF{nlist}_HNSW{M} 前缀,再按 Flat/SQ/PQ/PQfs/RaBitQ 拼接后缀;IndexPreTransform 还原 OPQ{M}_{d}、ITQ、PCA/PCAR 前缀;还处理 IndexRefine、IndexLSH、IndexRaBitQ 与 IndexIDMap/IDMap2 嵌套(注意 IndexIDMap2 必须先于 IndexIDMap 判断)。源码注释也坦诚:SQ8u/SQ4u 这类合成名不可通过 index_factory 往返。
12. evaluation.py:非平凡的检索结果评测
evaluation.py 对应 README 中"若干非平凡的搜索结果评测函数":
knn_intersection_measure(I1, I2)(第 17–22 行):两张 (nq, rank) 结果表的交集占比,衡量两种索引/参数配置的稳定性;filter_range_results(lims, D, I, thresh)与range_PR(lims_ref, Iref, lims_new, Inew, mode="overall")(第 29–76 行):range search 结果可当集合用 Precision-Recall 评测,内部用ThreadPool(20)并行计算每个查询的交集;counts_to_PR则支持overall/per-query 等模式,是OperatingPoints(第 300 行起,扫描多个阈值绘制工作点曲线)的底层;range_PR_multiple_thresholds(第 151 行起):一次计算多组半径下的 PR;check_ref_knn_with_draws(Dref, Iref, Dnew, Inew, rtol, atol):参考结果与待测结果的容差比对,显式处理**距离并列(draws)**导致的合法索引差异,是写测试时的实用断言工具;TimerIter/RepeatTimer(第 438/464 行):可计时的迭代器,方便在分块搜索脚本里统计吞吐。
13. clustering.py:Python kmeans 与两级聚类
contrib/clustering.py 对应 README 列出的三点内容:
- Python 实现的 kmeans(
kmeans,第 435 行起):用DatasetAssign抽象分配阶段,派生出DatasetAssignGPU(GEMM 加速分配)与DatasetAssignSparse(scipy 稀疏矩阵分配——这正是 README 说的"可用于稀疏矩阵等特殊数据类型"),并配sparse_assign_to_dense、reassign_centroids、imbalance_factor等辅助函数; - 两级聚类
two_level_clustering(xt, nc1, nc2, rebalance=True, clustering_niter=25, **args)(第 26–102 行):先对xt做faiss.Kmeans(d, nc1, max_points_per_centroid=2000)粗聚类,再按第一层桶规模按比例分配第二层质心数(rebalance开启时用bc_sum * nc2 // bc_sum[-1]的前差实现;关闭时按nc2 // nc1均匀切分),逐桶训练后np.vstack汇总。返回值是(centroids, iteration_stats); - 训练 IVF 索引
train_ivf_index_with_2level(index, xt, **args)(第 105 行起):对IndexPreTransform会先链式train/apply再递归处理内层;对IndexIVF断言metric_type == faiss.METRIC_L2后,把两级质心填入粗量化器——这是用 factory 之外的方式训练 IMI/大 nlist 索引的典型工具。
14. big_batch_search.py:逐桶批处理的 IVF 搜索
big_batch_search.py 解决 README 所述"大库放不进 RAM 且 查询量也很大"的场景:把查询按粗分配聚桶,对每个倒排列表一次性完成"该桶全部查询 × 该桶全部库向量"的批量匹配,再经堆合并得到全局 top-k。
入口 big_batch_search(index, xq, k, ...)(第 237 行起)的关键参数(docstring 即源码注释,原样继承):
method:三种计算方式——"index"(为每个桶建 Flat 索引)、"pairwise_distances"(解码码字后算全 pairwise 距离入堆)、"knn_function"(解码后调 knn);支持 IVFFlat、IVFPQ、IVFScalarQuantizer;pairwise_distances/knn:可传入自定义的 GPU 版本距离函数,使桶内计算落在 GPU 上;threaded:0 顺序执行;1 预取下一个桶;2 同时预取prefetch_threads个桶,计算与桶准备/结果写回做 tile 流水;use_float16:全链路 float16(GPU GEMM 更快);q_assign:可外部指定粗分配矩阵(形状nq × nprobe),与 ivf_tools.py 的 preassigned 思路呼应;checkpoint/checkpoint_freq(默认 7200,须为 threaded 倍数):长跑任务断点续算;start_list/end_list只处理部分倒排列表。
BigBatchSearcher(第 23 行起)承载全部数据组织:先 coarse_quantization()(以 65536 为批对 index.quantizer.search 求分配),再 reorder_assign() 用 faiss.matrix_bucket_sort_inplace 按桶重排查询(-1 无效分配归到 0 桶后裁掉),随后逐桶 prepare_bucket——残差编码索引会先减去质心 quantizer.reconstruct(l)。report() 会实时打印当前桶进度、各阶段耗时、ETA 与 faiss.get_mem_usage_kb() 内存占用,便于长跑监控。
15. 如何验证与延伸阅读
- tests/test_contrib.py 是 contrib 的主测试文件:除
TestComputeGT外,还覆盖 factory_tools、ivf_tools、ondisk 合并等路径,是确认各函数行为的第一手依据; - PyTorch 互操作测试:tests/torch_test_contrib.py(CPU);
- 分布式演示:demos/demo_client_server_ivf.py,配合 contrib/client_server.py 使用;
- 磁盘 IVF 演示:demos/demo_ondisk_ivf.py,与
ondisk.merge_ondisk的思路一致。
使用建议小结:单机内存放得下时优先用核心 API;库太大落盘用 ondisk.merge_ondisk;库太大且要多机用 client_server + RPC 客户端;训练期需要自定义分配/大 nlist 用 clustering.two_level_clustering;评测期需要精确 GT 或受控 range 结果用 exhaustive_search;深度学习流水线里则导入 torch_utils 后即可让张量零拷贝直喂 faiss。所有模块都随 faiss.contrib 自动可导入,外部依赖(GPU 版 faiss、PyTorch、h5py、scipy)按需自备即可。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00