最近在搞一个基于本地知识库的问答系统,用的是开源大模型+faiss做向量检索。embedding模型用的bge-base-zh,数据大概10万条,单条文本控制在500字以内。部署到生产环境后,发现每次检索都要2-3秒,这个延迟完全没法接受。我已经试过调整nprobe和nlist参数了,效果提升不明显。请问各位有没有什么优化经验?比如换更快的向量库(milvus?),或者对embedding做量化?另外,这种量级的数据量,是不是应该用倒排索引配合向量检索做混合搜索?求指点,卡在这块好几天了。
大佬们,RAG部署时向量检索太慢怎么办?用的是faiss+embedding
全部回复
共 167 条10万条数据量其实不算大,2-3秒肯定不正常。先看看是不是embedding那步在拖后腿,bge-base在CPU上跑512维要几十毫秒,但如果你每次请求都重新算query向量,那瓶颈就在这。可以试试把query向量也缓存起来,或者用onnx推理加速。
另外faiss的index类型很关键,IVF的话nprobe调高到几十试试,但更建议直接换HNSW,召回速度和精度平衡好很多,内存也就几百MB,你这数据量完全扛得住。混合搜索对你这场景帮助不大,除非有明确的关键词匹配需求,不然纯向量就够。
milvus其实更适合分布式和动态增删,你这固定10万条没必要上,反而增加运维成本。先优化faiss配置,大概率能压到200ms以内。
10万条这个量级faiss不该这么慢啊,你确认下是不是embedding那步耗时占了大头,bge-base在CPU上推理本身就慢,建议单独把向量化做成异步或者上GPU。nprobe调到几十基本到头了,再大就退化成暴力搜索了,另外你试试用HNSW索引替代IVF,召回和速度都会好不少。混合搜索倒是个思路,但别急着上,先看下你实际检索的瓶颈到底在IO还是计算,做个profiling再动手。
看到你这个延迟数据,我第一反应是bge-base这个模型本身可能才是瓶颈,10万条500字内的数据其实不算大,faiss纯CPU检索理论上应该在几十毫秒级别。你可以先测一下把embedding查询单独拎出来看耗时多少,如果embedding就要1秒多,那换milvus也救不了。另外nprobe调参没效果的话,试试把faiss的索引类型从IVF换成HNSW,小批量数据上HNSW的召回和速度往往比IVF稳得多,内存占用也可控。量化这块我建议先别急着上,你数据量不大,用SQ8或者PQ反而可能掉精度,不如先确保索引是训练好的,而且faiss有个问题就是默认不启用多线程,你检查下是不是没设faiss.cvar.omp_num_threads,这个对单机部署影响特别大。混合搜索的话,10万条数据其实关键词过滤就能做,倒排索引有点杀鸡用牛刀了,不如先把向量检索的耗时拆解出来定位清楚再动手。
说实话你这数据量真不算大,十万条才几十MB级别,faiss纯CPU跑都不该这么慢,2-3秒大概率是卡在embedding推理上而不是检索本身。建议你先分步测下耗时,把向量化那步单独拎出来看,bge-base在CPU上处理长文本确实容易成为瓶颈,可以试试把输入长度截断到256甚至128,或者换更轻量的模型比如m3e-small。至于量化,faiss的PQ或者标量量化对你这规模收益不大,反而可能掉精度,不如直接用IVF+HNSW混合索引,nlist设成1000左右,nprobe调到50-100,检索应该能压到几十毫秒。另外milvus这种重服务端的东西对单机小项目反而增加运维负担,不太建议现在上。混合搜索的话,如果你的query是问句风格,BM25和向量得分做个线性融合确实能提升召回,但前提是你得先把es或者tantivy这类全文检索搭起来,成本不小。最后检查下是不是每次请求都重新加载模型了,模型常驻内存能省一大截时间。
10万条这量级真不算大,faiss完全扛得住,问题八成出在bge-base的推理耗时上,建议先给embedding加个缓存或者换成更轻量的模型试试。另外nprobe调太高反而会拖慢速度,试试把nlist设成1000左右,nprobe保持10以内,查准率损失不大的。如果还不行,可以考虑用onnxruntime或者TensorRT把embedding模型加速一下,比换milvus成本低多了。混合搜索这块,我倒是觉得可以先不用上倒排,毕竟你这纯向量检索场景,瓶颈不在召回率上。
10万条数据2-3秒确实不正常,先查查是不是没建IVF索引或者embedding那步拖后腿了。
10万条数据faiss检索要2-3秒确实不太正常,正常情况应该几十毫秒就出结果了。先确认下是不是把embedding模型推理时间也算进去了?bge-base在CPU上跑一次可能就1秒多,换成GPU或者用onnx量化能快不少。另外faiss建索引时用IVF+PQ量化能大幅提速,但10万这个量级其实用HNSW就够了,召回和速度都比较均衡。混合搜索确实值得搞,尤其你们是中文知识库,关键词匹配能补上语义检索的短板。