电商重排序 API:提升商品搜索相关性
ZooData Team2026年4月17日4 min 阅读
ecommercererankingsearchapisemantic-search
商品搜索是每个电商平台的第一入口。用户输入"红色连衣裙",期望看到连衣裙——而不是红色裤子、红色油漆或红色手机壳。传统的关键词匹配(BM25、TF-IDF)能解决部分问题,但在同义词、语义改写和意图不匹配的场景下表现不佳。重排序器(Reranker)位于初始检索之上,通过语义相关性对结果重新排序,在不替换现有搜索基础设施的前提下显著提升 Top-K 结果质量。
为什么电商搜索需要重排序
电商搜索有其独特的挑战,通用重排序器难以很好地应对:
- 属性匹配 — "带主动降噪的无线蓝牙耳机"应该让带有 ANC 功能的产品排名更高,即使商品标题写的是"降噪"而非"ANC"。
- 品类消歧 — "苹果"在用户上下文暗示科技产品时,应该优先展示电子产品而非水果。
- 跨语言商品标题 — 很多电商平台的商品标题混合了英文品牌名和本地语言描述。
- 长尾查询 — "42码防水宽脚登山靴"这样的精确查询需要深度语义理解,才能匹配分散在标题、卖点和描述中的商品属性。
我们的重排序器在电商商品数据上进行了微调,能够开箱即用地理解商品属性、品牌名称和购物意图。
API 设计
API 接受一批搜索查询,每个查询对应一组商品文档,然后返回按相关性排序的文档。
端点: POST https://api.apiclaw.io/openapi/v2/model/ecommerce-rerank
积分: 每个查询消耗 1 积分。一个包含 3 个查询和 50 个文档的请求消耗 3 积分。
限制:
- 每次请求最多 10 个查询
- 每个查询最多 100 个文档
- 每个查询最多 1,000 字符
- 每个文档最多 10,000 字符
请求
{
"queries": ["红色连衣裙", "夏季凉鞋"],
"documents": [
["红色碎花棉质夏季连衣裙", "蓝色修身牛仔裤", "女士优雅红色晚礼服"],
["Nike Air Zoom Pegasus 40 跑步鞋", "真皮夏季凉鞋系列", "蓝色修身牛仔裤"]
],
"topK": 2
}
响应
{
"success": true,
"data": {
"results": [
[
{ "index": 2, "relevanceScore": 0.9341, "document": "女士优雅红色晚礼服" },
{ "index": 0, "relevanceScore": 0.8756, "document": "红色碎花棉质夏季连衣裙" }
],
[
{ "index": 1, "relevanceScore": 0.8912, "document": "真皮夏季凉鞋系列" },
{ "index": 0, "relevanceScore": 0.7234, "document": "Nike Air Zoom Pegasus 40 跑步鞋" }
]
],
"modelName": "qwen3_reranker:Qwen/Qwen3-Reranker-0.6B (reranker_v02)"
},
"meta": {
"requestId": "req_8a3f2b1c4d567890",
"timestamp": "2026-04-17T10:30:00.000000Z",
"creditsRemaining": 997,
"creditsConsumed": 2
}
}
响应字段说明:
results— 嵌套数组:results[i]包含queries[i]对应的排序结果,按relevanceScore降序排列results[i][j].index— 文档在documents[i]中的原始索引results[i][j].relevanceScore— 归一化相关性分数,范围 0 到 1results[i][j].document— 文档文本modelName— 重排序模型名称和版本
代码示例
示例 1:基础重排序(curl)
# 对单个查询进行商品重排序
curl -s -X POST https://api.apiclaw.io/openapi/v2/model/ecommerce-rerank \
-H "Authorization: Bearer hms_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"queries": ["无线蓝牙耳机"],
"documents": [
[
"Sony WH-1000XM5 无线降噪头戴式耳机",
"USB-C 充电线 6英尺编织线",
"Bose QuietComfort Ultra 无线耳塞",
"铝合金可调节笔记本支架"
]
],
"topK": 2
}'
# => results[0] = [{index: 0, relevanceScore: 0.95, ...}, {index: 2, relevanceScore: 0.88, ...}]
示例 2:Python — 关键词搜索后重排序
import httpx
APICLAW_URL = "https://api.apiclaw.io/openapi/v2/model/ecommerce-rerank"
APICLAW_KEY = "hms_live_YOUR_API_KEY"
def rerank_search_results(query: str, product_titles: list[str], top_k: int = 10) -> list[dict]:
"""按语义相关性对商品标题重新排序。"""
resp = httpx.post(
APICLAW_URL,
headers={"Authorization": f"Bearer {APICLAW_KEY}"},
json={
"queries": [query],
"documents": [product_titles],
"topK": top_k,
},
timeout=30.0,
)
result = resp.json()
if not result["success"]:
raise RuntimeError(f"重排序失败:{result['error']}")
return result["data"]["results"][0]
# 示例:关键词搜索返回 20 个商品,重排序取 Top 3
keyword_results = [
"红色碎花棉质夏季连衣裙",
"红色 LED 可调台灯",
"女士优雅红色晚礼服",
"红色 iPhone 15 手机壳",
"休闲红色 V 领中长裙",
]
top_3 = rerank_search_results("红色连衣裙", keyword_results, top_k=3)
for item in top_3:
print(f" [{item['relevanceScore']:.3f}] {item['document']}")
# => [0.934] 女士优雅红色晚礼服
# => [0.876] 红色碎花棉质夏季连衣裙
# => [0.812] 休闲红色 V 领中长裙
示例 3:Python — 多查询批量对比
import httpx
APICLAW_URL = "https://api.apiclaw.io/openapi/v2/model/ecommerce-rerank"
APICLAW_KEY = "hms_live_YOUR_API_KEY"
def compare_query_variants(
query_variants: list[str], product_catalog: list[str]
) -> dict[str, list[dict]]:
"""对比不同查询表述对同一商品集的排序效果。"""
resp = httpx.post(
APICLAW_URL,
headers={"Authorization": f"Bearer {APICLAW_KEY}"},
json={
"queries": query_variants,
"documents": [product_catalog] * len(query_variants),
},
timeout=30.0,
)
data = resp.json()["data"]
return {
query: results
for query, results in zip(query_variants, data["results"])
}
# 对比"运动鞋"和"跑步鞋"对同一商品集的排序差异
results = compare_query_variants(
["运动鞋", "跑步鞋"],
[
"Nike Air Max 90 休闲运动鞋",
"Adidas Ultraboost Light 跑步鞋",
"Converse Chuck Taylor 经典帆布鞋",
"ASICS Gel-Kayano 30 稳定跑鞋",
],
)
for query, ranked in results.items():
print(f"\n'{query}' 最佳匹配:{ranked[0]['document']}({ranked[0]['relevanceScore']:.3f})")
示例 4:TypeScript — Next.js 搜索增强
const APICLAW_URL = "https://api.apiclaw.io/openapi/v2/model/ecommerce-rerank";
const APICLAW_KEY = process.env.APICLAW_API_KEY!;
interface RankedDocument {
index: number;
relevanceScore: number;
document: string;
}
async function rerankProducts(
query: string,
productTitles: string[],
topK?: number,
): Promise<RankedDocument[]> {
const res = await fetch(APICLAW_URL, {
method: "POST",
headers: {
Authorization: `Bearer ${APICLAW_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ queries: [query], documents: [productTitles], topK }),
});
const data = await res.json();
if (!data.success) throw new Error("重排序失败");
return data.data.results[0];
}
// 在搜索 API 路由中使用
export async function GET(req: NextRequest) {
const query = req.nextUrl.searchParams.get("q") ?? "";
const keywordResults = await searchByKeyword(query); // 现有搜索
const titles = keywordResults.map((p) => p.title);
const ranked = await rerankProducts(query, titles, 20);
const reorderedProducts = ranked.map((r) => keywordResults[r.index]);
return NextResponse.json({ products: reorderedProducts });
}
模型详情
重排序器由 Qwen3-Reranker-0.6B 驱动,这是一个 0.6B 参数的交叉编码器模型,针对电商商品匹配进行了微调。核心特点:
- 交叉编码器架构 — 联合编码查询和文档,比双编码器检索实现更深层的语义匹配
- 电商优化 — 在跨多个品类的商品标题、描述和搜索查询上进行微调
- 归一化分数 — 输出分数归一化到 [0, 1],方便阈值设定和比较
- 批量高效 — 在单次请求中处理多个查询,每个查询可配置独立的文档集
适用场景
| 场景 | 收益 |
|---|---|
| 关键词搜索(BM25/Elasticsearch)后 | 提升关键词匹配遗漏的语义相关结果 |
| 商品推荐 | 按用户当前搜索上下文对候选商品重排序 |
| 商品目录去重 | 对商品对评分发现语义重复 |
| 搜索质量评估 | 对比不同查询表述的排序质量 |
参考文献
- Qwen Team. "Qwen3-Reranker". Hugging Face, 2025.
- Nogueira, R. & Cho, K. "Passage Re-ranking with BERT". arXiv:1901.04085, 2019.
- Gao, L., Ma, X., Lin, J. & Callan, J. "Precise Zero-Shot Dense Retrieval without Relevance Labels". arXiv:2212.10496, 2022.