当前位置: 首页 > article >正文

实战指南:在 CPU 上 200ms 内搜索 4000 万文档

实战指南在 CPU 上 200ms 内搜索 4000 万文档使用二进制嵌入和 Int8 重排序摘要这篇文章Search 40M documents in under 200ms介绍了一种在纯CPU环境下高效处理大规模语义搜索的技术方案。文章的技术亮点在于结合了二进制嵌入Binary Embeddings进行快速初筛和Int8嵌入进行重排序Rescoring1 引言4000 万文档。一个 CPU。没有 GPU。二进制搜索加上 int8 重排序如何悄悄改写大规模语义搜索的规则。当你处理嵌入足够长的时间时你会遇到一种非常具体的挫折感。你终于让检索工作正常了。它很准确。感觉很智能。你为它感到骄傲。然后你看了看账单。或者更糟糕的是RAM 使用率。或者比这更糟糕的是——当你意识到你的“简单”语义搜索需要180GB 的内存才能存在的那一刻。这通常是那种安静的假设潜入的地方“好吧……我想这只是正确进行向量搜索的成本。”但也许不是。因为这是我在滚动鼠标时停下来的原因你可以搜索4000 万个文本在 ~200ms 内在纯 CPU上使用8GB RAM和45GB 磁盘没有 GPU。没有奇异的硬件。没有魔法。只是一个非常深思熟虑的推理策略。一旦你看到它你就无法忽视它。2、关于 fp32 嵌入的不舒服的真相让我们大声说出来。我们要么默认使用float32 嵌入因为那是模型给我们的。我们将它们视为神圣的。不可触碰的。高精度或什么都没有。但想想我们在检索过程中实际上在做什么。我们不是在解物理方程。我们在对文档进行排名。而排名特别是在漏斗的顶部是令人惊讶地宽容的。这就是整个方法滑过的裂缝。3、技巧一旦你剥去神秘感设置几乎是无聊的二进制搜索用于召回。Int8 重排序用于精度。就是这样。你没有丢弃质量。你分阶段进行。你让廉价的表示先做繁重的工作然后只在重要的地方带回精度。这是完整流程的工作原理。4、推理策略一步步来让我们慢慢地过一遍就像我们在一起调试一样。5、嵌入查询我们从你期望的地方开始。一个密集的嵌入模型。一个标准的 fp32 向量。start_time time.time query_embedding model.encode_query (query) embed_time time.time() start_time还没有什么花哨的。这是你的参考信号。你稍后会信任的东西。6、将查询量化为二进制现在是思维方式的第一次转变。我们将那个 fp32 查询嵌入量化为二进制。同样的语义方向。32 倍小的表示。start_time time.time query_embedding_ubinary quantize_embeddings( query_embedding.reshape(1, 1), ubinary ) quantize_time time.time() start_time这一步很快。几乎快得可疑。它解锁了后面的一切。7、搜索二进制索引这就是规模突然不再可怕的地方。二进制索引很小。它们很快。它们快乐地生活在内存中。你可以在这里选择精确或近似搜索。index binary_ivf_index if use_approx else binary_index start_time time.time() _scores, binary_ids index.search query_embedding_ubinary, top_k rescore_multiplier ) binary_ids binary_ids[0] search_time time.time() start_time与其问“4000 万个文档中哪个最好”你在问“哪 ~40 个看起来有希望”这种重新框架很重要。8、为顶级候选者加载 int8 嵌入既然我们已经缩小了范围我们重新引入更多的信号。我们只为顶级的二进制命中加载int8 嵌入。start_time time.time() int8_embeddings np.array( title_text_int8_dataset [binary_ids][embedding], dtypenp.int8 ) load_int8_time time.time() start_time仍然很小。仍然很便宜。但比二进制更具表现力。9、使用原始 fp32 查询进行重排序这是精度回归的时刻。我们将原始 fp32 查询嵌入与int8 文档嵌入进行评分。start_time time.time() scores query_embedding int8_embeddings.T rescore_time time.time() start time这一步几乎不花费任何成本。它为你买回了你早期“丢失”的大部分质量。10、排序并挑选最佳结果start_time time.time() indices scores.argsort() [::-1][:top_k] top_k_indices binary_ids[indices] top_k_scores scores [indices] sort_time time.time() start_time此时你基本上完成了排名。11、加载实际文本只有现在你才接触标题、URL 和内容。start_time time.time() top_k_titles title_text_int8_dataset [top_k_indices] [title] top_k_urls title_text_int8_dataset [top_k_indices] [url] top_k_texts title_text_int8_dataset [top_k_indices] [text] top_k_titles [f [{title}] ({url}) for title, url in zip(top_k_titles, top_k_urls)] load_text_time time.time() start_time这正是你_应该_加载它们的时候。而不是更早。12、实际上重要的数字这是在4000 万个维基百科文本上的真实运行Embed Time: 0.0833 s Quantize Time: 0.0000 s Search Time: 0.0464 s Load int8 Time: 0.0263 s Rescore Time: 0.0006 s Sort Time: 0.0000 s Load Text Time: 0.0192 s Total Retrieval Time: 0.0925 s再读一遍。在 100ms 内端到端。在 CPU 上。你可以现在就自己尝试无需登录https://huggingface.co/spaces/sentence-transformers/quantized-retrieval13、为什么这行得通以及为什么起初感觉不对它感觉不对因为我们被教导要不惜一切代价保护精度。但检索不是分类。它不是回归。它甚至不是生成。它是分类。二进制嵌入在排除事物方面是现象级的。Int8 嵌入在排名竞争者方面很棒。Fp32 在你真正需要细微差别时是最好的——一旦你剩下 40 个文档这种情况很少见。因此与其到处支付 fp32 成本不如像聚光灯一样分阶段进行精度。先宽光束。后窄光束。14、存储和内存让我们将其与标准 fp32 设置进行比较。15、Float32 检索基线RAM: ~180GB磁盘: ~180GB速度: 慢成本: 痛苦16、二进制 int8 检索二进制索引:32 倍更小Int8 嵌入:4 倍更小RAM 使用: ~6GB磁盘使用: ~45GB这是关键所在。你只将二进制索引保留在内存中。那是真正的节省复合的地方。17、性能权衡让我们不要假装零损失。这是实验显示的| Representation | Index Size | Speed | Performance | | ---------------- | ----------- | ---------------- | ----------- | | float32 | 1× | 1× | 100% | | int8 / uint8 | 4× smaller | up to 4× faster | ~99.3% | | binary / ubinary | 32× smaller | up to 45× faster | ~96% |现在是重要的部分。通过二进制搜索检索更多候选者并使用 int8 对它们进行重排序你恢复了~99% 的 fp32 质量。那最后的 1% 几乎不花费你任何东西。18、这在实践中改变了什么老实说很多。这意味着你不需要 GPU 进行大规模语义搜索你可以在商品硬件上发布严肃的检索你不再到处支付 fp32 的“奢侈税”你可以扩展集合而无需重写所有内容也许更大的转变是心理上的。我们一直像对待易碎的玻璃一样对待嵌入。它们不是。它们是工具。当你停止对每颗钉子都使用一把锤子时工具效果最好。19、如果你要从中带走一件事分阶段思考。不要问“什么是最准确的表示”问“在管道的这个点上什么足够准确”二进制第一。Int8 第二。精度最后。一旦你这样看检索回到到处暴力 fp32 感觉……有点不负责任。也许这就是隐藏在这里的真正教训。不是量化很聪明。而是工程判断仍然胜过暴力即使在巨型模型的时代。参考文献实战指南在 CPU 上 200ms 内搜索 4000 万文档使用二进制嵌入和 Int8 重排序

相关文章:

实战指南:在 CPU 上 200ms 内搜索 4000 万文档

实战指南:在 CPU 上 200ms 内搜索 4000 万文档:使用二进制嵌入和 Int8 重排序 摘要:这篇文章Search 40M documents in under 200ms介绍了一种在纯CPU环境下高效处理大规模语义搜索的技术方案。文章的技术亮点在于结合了二进制嵌入&#xff08…...

Simufact.Forming工艺链仿真实战:从冷成型到热处理的完整流程配置技巧

Simufact.Forming工艺链仿真实战:从冷成型到热处理的完整流程配置技巧 在高端制造领域,工艺链仿真是确保产品质量和生产效率的关键环节。Simufact.Forming作为业界领先的金属成型仿真解决方案,其工艺链功能能够无缝衔接从冷成型到热处理的完整…...

链表(两数相加)(1)

一.题目 2. 两数相加 - 力扣(LeetCode) 二.思路讲解 2.1 审题 题目给出两个非空链表,每个链表表示一个非负整数,并且数字是逆序存储的,即链表的头节点对应数字的最低位。例如,链表 2->4->3 表示数字…...

从H.264到AV1:主流视频编码标准的演进、选型与实战场景剖析

1. 视频编码标准的发展脉络 我第一次接触视频编码是在2005年,当时用手机拍摄的3GP视频文件总是模糊不清。后来才知道,这背后是MPEG-4 Part 2编码在起作用。如今视频编码技术已经迭代了好几代,从最早的MPEG-2到现在的AV1,每一次升级…...

Creo混合与扫描混合实战:从基础到高级建模技巧

1. Creo混合与扫描混合功能入门指南 第一次打开Creo的混合功能时,我完全被那些参数搞懵了。后来才发现,这个看似复杂的功能其实就像搭积木一样简单。混合建模的核心思想就是把不同形状的截面按照特定规则连接起来,形成三维实体。比如你想做个…...

java架构一/1:微服务电商/地基/登录

一、构建聚合工程(Java-Maven)foodie-dev为父工程,其他为子模块。foodie-dev-api的pom.xml引入依赖-service,-service引入-mapper,-mapper引入-pojo,-pojo引入-common。二、使用PDMan进行数据库建模&#x…...

OpenClaw多模态实践:千问3.5-27B图片理解+文件整理自动化

OpenClaw多模态实践:千问3.5-27B图片理解文件整理自动化 1. 为什么需要自动化图片管理 上周整理项目资料时,我发现桌面上散落着237张截图——有会议纪要片段、代码报错提示、参考文档关键页,甚至还有随手截的灵感草图。手动分类这些文件花了…...

AI大揭秘:从ChatGPT到深度学习,普通人如何抓住AI风口?

一提及AI,大家脑海里想的是什么呢?是Deepseek、豆包、元宝等软件应用,还是能跑会跳的机器人?或者是那些能自己跑的车子、能自己运转的机器? 这些都是AI,都是人工智能。 基本概念 AI是英文Artificial Intell…...

OpenClaw(小龙虾)Windows 11 一键部署教程|2026 最新版|零代码・免配置・解压即用

适用系统:Windows 11 专业版 / 家庭版 / 正式版(全版本兼容) 项目介绍:OpenClaw 是 GitHub 星标 28W 的开源本地 AI 智能体,可自动操控电脑、整理文件、浏览器自动化、办公自动化,被国内用户称为小龙虾&am…...

从标注到训练:手把手教你用Labelme制作YOLOv8-Pose可用的关键点数据集

从标注到训练:手把手教你用Labelme制作YOLOv8-Pose可用的关键点数据集 在计算机视觉领域,关键点检测技术正逐渐成为研究热点。无论是人体姿态估计、面部表情识别还是工业质检中的零件定位,准确的关键点检测都是实现这些应用的基础。然而&…...

MySQL 索引特性与性能优化全解

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C知识分享》 《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录前言:一. 索引是什么1.1 初…...

SentenceTransformer:计算句子嵌入的模型

原文:towardsdatascience.com/sentencetransformer-a-model-for-computing-sentence-embedding-e8d31d9e6a8f 在这篇帖子中,我们探讨了 2019 年发布的 SentenceTransformer [1],它具有双编码器架构,并将 BERT 调整为产生高效的句子…...

题目整理之线性dp

周赛137_D小苯的序列涂色 #include<bits/stdc.h> #define int long long #define fi first #define se second using namespace std; const int mod1e97; typedef pair<int,int>pii; const int N3e5; int dx[4]{1,-1,0,0}; int dy[4]{0,0,1,-1}; int num[N],inv[N]…...

新手避坑指南:用Pandas高效合并CIC-IDS-2018的10个CSV文件(附内存优化技巧)

新手避坑指南&#xff1a;用Pandas高效合并CIC-IDS-2018的10个CSV文件&#xff08;附内存优化技巧&#xff09; 网络安全数据分析的第一步往往是从处理原始数据集开始。CIC-IDS-2018作为业内广泛使用的基准数据集&#xff0c;其分散在10个CSV文件中的特征数据给初学者带来了不小…...

OpenClaw个人知识库构建:Qwen3-14b_int4_awq自动标注与归档

OpenClaw个人知识库构建&#xff1a;Qwen3-14b_int4_awq自动标注与归档 1. 为什么需要自动化知识管理 作为一个长期与技术文档打交道的开发者&#xff0c;我的本地硬盘里堆积着超过20GB的研究资料——从PDF论文、Markdown笔记到代码片段和会议记录。传统文件夹分类早已失效&a…...

校正协变量的相关:偏相关分析

当你想研究两个变量&#xff08;X 和 Y&#xff09;的关系&#xff0c;但担心其他变量&#xff08;Z&#xff09;可能干扰这个关系时&#xff0c;偏相关分析 (Partial Correlation) 可以在剔除协变量的影响后&#xff0c;计算 X 和 Y 之间更“纯粹”的关联。 1. 核心定义 偏相关…...

数字游民工作流:OpenClaw+千问3.5-27B自动处理跨境邮件

数字游民工作流&#xff1a;OpenClaw千问3.5-27B自动处理跨境邮件 1. 为什么需要自动化邮件处理 作为数字游民&#xff0c;我每天需要处理来自不同时区的客户邮件。这些邮件往往混杂着英语、西班牙语和中文&#xff0c;且包含大量模糊的需求描述。最痛苦的是凌晨三点被手机提…...

OpenClaw+Qwen3-14b_int4_awq:自动化文档生成工具

OpenClawQwen3-14b_int4_awq&#xff1a;自动化文档生成工具 1. 为什么需要自动化文档生成 作为一名技术写作者&#xff0c;我经常面临一个困境&#xff1a;代码写完了&#xff0c;文档却迟迟无法完成。每次面对空白的Markdown文件&#xff0c;总有种无从下笔的感觉。更糟糕的…...

基于SpringBoot + Vue的人工智能时代个人计算机的安全防护科普系统

文章目录前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论五、项目代码参考六、数据库代码参考七、项目论文示例结语前言 &#x1f49b;博主介绍&#…...

NaViL-9B多场景落地:物流运单图像识别+地址结构化+异常标记

NaViL-9B多场景落地&#xff1a;物流运单图像识别地址结构化异常标记 1. 物流行业的AI变革机遇 现代物流行业每天处理数以亿计的运单&#xff0c;传统人工处理方式面临三大挑战&#xff1a; 效率瓶颈&#xff1a;人工录入一张运单平均耗时30秒&#xff0c;高峰期处理能力不足…...

基于SpringBoot + Vue的鲜花销售系统(角色:用户、商家、管理员)

文章目录前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论五、项目代码参考六、数据库代码参考七、项目论文示例结语前言 &#x1f49b;博主介绍&#…...

小程序常用页面跳转 5 种方式汇总(开发常备手册)

小程序多页面协作离不开路由跳转&#xff0c;不同场景对应不同跳转 API&#xff0c;今天一次性整理齐全&#xff0c;开发随时查阅。保留当前页跳转&#xff08;普通内页&#xff09;wx.navigateTo({url:"/pages/detail/detail"})关闭当前页再跳转wx.redirectTo({url:…...

Python脚本打包成.exe方法

利用 pyinstaller打包 先安装这个库 pip install pyinstaller安装完成后&#xff0c;就可台利用pyinstaller进行打包了 在脚本文件的目录下切到cmd中&#xff0c;执行以下 pyinstaller -F tcping.py-F参数&#xff1a; 表示覆盖打包&#xff0c;不管我们打包几次&#xff0c;都…...

SEO 优化师如何处理网站收录和排名下降的问题

SEO 优化师如何处理网站收录和排名下降的问题 在数字营销中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;是一个至关重要的环节&#xff0c;尤其是对于那些希望在百度上获得高排名和流量的网站。即使是最优秀的SEO策略&#xff0c;也可能会在某些时候面临网站收录和排…...

Linux ioctl系统调用实战

Linux ioctl系统调用实战 ioctl&#xff08;input/output control&#xff09;是Linux系统中一个强大的系统调用&#xff0c;用于设备控制和配置。从网络接口配置到串口通信&#xff0c;ioctl无处不在。本文将深入讲解ioctl的原理和实战应用。 一、ioctl概述 1.1 什么是ioctl i…...

嵌入式轻量级调试追踪组件dbg-trace设计与应用

1. 项目概述dbg-trace是一个面向嵌入式系统的轻量级调试追踪&#xff08;Debug & Trace&#xff09;组件&#xff0c;其核心设计目标是在资源受限的 MCU 环境中提供可配置、低开销、高可靠性的日志输出能力。它不依赖标准 C 库的printf实现&#xff0c;而是基于“追踪端口”…...

Obsidian插件实战:5个提升笔记效率的神器(附避坑指南)

Obsidian插件实战&#xff1a;5个提升笔记效率的神器&#xff08;附避坑指南&#xff09; 如果你正在寻找能够真正提升Obsidian笔记效率的插件组合&#xff0c;这篇文章将为你揭示5个经过实战检验的效率神器。不同于泛泛而谈的插件列表&#xff0c;我们聚焦于那些能够形成工作…...

MySQL索引优化快速入门

这里需要知道什么是B树 从数据结构角度简单分析&#xff1a; 二叉树和B树可以简单理解为通过二分法减少查询的次数&#xff0c;但是仍存在严重的性能问题 1&#xff0c;插入顺序不对时&#xff0c;会退化为链表&#xff0c;时间复杂度由O(logn)变成O(n)。 2. 大数据情况下…...

刷题不再难:用代码随想录和Hot100打造你的算法思维

算法思维跃迁&#xff1a;从代码随想录到Hot100的实战精进指南 1. 算法能力提升的黄金路径 在技术面试中&#xff0c;算法能力往往是区分候选人的关键指标。但许多开发者在刷题过程中常陷入"刷了就忘"的困境&#xff0c;缺乏系统性训练方法。本文将揭示如何通过代码随…...

双向buck-boost电路仿真模型-储能双向DCDC变换器 电压电流双闭环PI控制 蓄电池充放电模式可切换 恒流充电_恒压输出 Matlab_Simulink模型

双向buck-boost电路仿真模型-储能双向DCDC变换器 电压电流双闭环PI控制 蓄电池充放电模式可切换 恒流充电/恒压输出 Matlab/Simulink模型核心控制算法&#xff1a;双闭环 PI 控制器 (MATLAB Function/S-Function) 这是模型的“大脑”。它需要根据模式切换&#xff0c;决定是外环…...