共计 2121 个字符,预计需要花费 6 分钟才能阅读完成。
痛点分析:电商搜索的三大挑战
电商平台的搜索功能面临几个核心挑战,这些挑战直接影响用户体验和转化率。

- 语义歧义:用户输入的查询往往简短且模糊。比如搜索“苹果”,用户可能想找水果、手机或电脑。传统关键词匹配无法区分这些意图。
- 冷门商品召回:长尾商品由于销量低、描述文本少,很难通过传统搜索算法有效召回。据统计,电商平台中约 60% 的商品属于长尾。
- 高并发响应:大促期间搜索 QPS 可能超过 10 万,系统需要在 200ms 内返回结果,这对语义模型的推理速度提出极高要求。
技术选型:为什么选择 BERT+Faiss
在对比了几种主流方案后,我们最终选择了 BERT+Faiss 的组合。
- BERT vs SimCSE:BERT 通过预训练学习到丰富的语义表示,而 SimCSE 更适合句子级相似度任务。电商搜索需要同时理解商品标题、属性和用户查询的细粒度语义,BERT 更合适。
- Faiss 的优势:Faiss 是 Facebook 开源的向量检索库,支持 GPU 加速和多种索引类型。实测显示,在 10 亿级向量库中,Faiss 的检索速度比 ES 快 20 倍以上。
核心实现
BERT 微调步骤
我们使用 HuggingFace 的 transformers 库微调 BERT 模型。以下是关键代码片段:
from transformers import BertTokenizer, BertModel
import torch
# 加载预训练模型
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
# 构造训练样本(关键技巧:加入商品属性)train_samples = [("iphone 13", "electronics/phone/apple"),
("red apple", "food/fruit")
]
# 微调代码(简化版)optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)
for query, category in train_samples:
inputs = tokenizer(query, return_tensors="pt")
outputs = model(**inputs)
# 自定义损失函数...
Faiss 索引构建
我们选择 IVF_PQ 索引平衡速度和精度:
import faiss
# 生成随机向量模拟商品嵌入
d = 768 # BERT 向量维度
nb = 100000 # 数据库大小
xb = np.random.random((nb, d)).astype('float32')
# 构建索引
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFPQ(quantizer, d, 100, 16, 8) # 100 个聚类中心, 16 个子空间, 8bits
index.train(xb)
index.add(xb)
# 保存索引
faiss.write_index(index, "ecommerce.index")
分层检索架构
我们采用粗排 + 精排的两阶段架构:
graph TD
A[用户查询] --> B(向量化)
B --> C{Faiss 粗排}
C -->|Top 1000| D[BERT 精排]
D --> E(Top 50 结果)
- 粗排:Faiss 快速召回 1000 个候选,耗时 <50ms
- 精排:BERT 对 Top1000 做精细排序,耗时约 150ms
性能优化
模型量化
通过 8bit 量化减小模型体积,同时控制精度损失 <2%:
from torch.quantization import quantize_dynamic
# 动态量化模型
model_quantized = quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8
)
向量缓存设计
使用 Redis 缓存高频查询向量,设置 TTL 为 6 小时:
import redis
import pickle
r = redis.Redis(host='localhost', port=6379)
def cache_vector(query: str, vector: np.ndarray):
r.setex(f'vector:{query}',
3600*6, # TTL
pickle.dumps(vector)
)
避坑指南
- Faiss 内存问题:
- 使用
faiss.index_factory时设置nprobe=32避免内存暴涨 - 定期调用
reset()清理缓存 -
对大数据集使用
IndexShards分片 -
混合检索策略:
- 对高点击 Query 保留传统倒排索引
- 当语义结果 CTR 低于阈值时自动 fallback 到关键词搜索
复现 Checklist
- 数据准备:至少 10 万商品标题 + 类目
- 环境要求:
- GPU: NVIDIA V100 16GB
- RAM: >=64GB
- 关键参数:
- Faiss: nlist=100, m=16
- BERT: batch_size=32, lr=2e-5
结语
这套方案在某服装电商落地后,搜索准确率提升 37%,长尾商品曝光量增加 2.3 倍。建议读者先在小数据集验证效果,再逐步扩展到全量商品。遇到性能瓶颈时,优先考虑优化 Faiss 参数而非升级硬件。
正文完
