搜索API对接指南-07-微服务接口(Embedding-Reranker-Translation)
本篇覆盖向量服务(Embedding)、重排服务(Reranker)、翻译服务(Translation)以及 Indexer 服务内的内容理解字段生成(原文第 7 章)。
7. 微服务接口(向量、重排、翻译)
以下三个微服务独立部署,外部系统可直接调用。它们被搜索后端(6002)和索引服务(6004)内部使用,也可供其他业务系统直接对接。
| 服务 | 默认端口 | Base URL | 说明 |
|---|---|---|---|
| 向量服务(文本) | 6005 | http://localhost:6005 |
文本向量化,用于 query/doc 语义检索 |
| 向量服务(图片 / 多模态 CN-CLIP) | 6008 | http://localhost:6008 |
图片向量 /embed/image;同空间文本向量 /embed/clip_text(以文搜图等) |
| 翻译服务 | 6006 | http://localhost:6006 |
多语言翻译(云端与本地模型统一入口) |
| 重排服务 | 6007 | http://localhost:6007 |
对检索结果进行二次排序 |
生产环境请将 localhost 替换为实际服务地址。
服务管理入口与完整启停规则见:docs/Usage-Guide.md -> 服务管理总览。
7.1 向量服务(Embedding)
- Base URL:
- 文本:
http://localhost:6005(可通过EMBEDDING_TEXT_SERVICE_URL覆盖) - 图片:
http://localhost:6008(可通过EMBEDDING_IMAGE_SERVICE_URL覆盖)
- 文本:
- 启动:
- 文本:
./scripts/start_embedding_text_service.sh - 图片:
./scripts/start_embedding_image_service.sh
- 文本:
- 依赖:
- 文本向量后端默认走 TEI(
http://127.0.0.1:8080) - 图片向量依赖
cnclip(grpc://127.0.0.1:51000) - TEI 默认使用 GPU(
TEI_DEVICE=cuda);当配置为 GPU 且不可用时会启动失败(不会自动降级到 CPU) - cnclip 默认使用
cuda;若配置为cuda但 GPU 不可用会启动失败(不会自动降级到cpu) - 当前单机部署建议保持单实例,通过文本/图片拆分 + 独立限流隔离压力
- 文本向量后端默认走 TEI(
补充说明:
- 文本和图片现在已经拆成不同进程 / 不同端口,避免图片下载与编码波动影响文本向量化。
- 服务端对 text / image 有独立 admission control:
TEXT_MAX_INFLIGHTIMAGE_MAX_INFLIGHT
- 当超过处理能力时,服务会直接返回过载错误,而不是无限排队。
- 文本与图片服务均支持
priorityquery 参数(图片不做队列插队,仅 admission 规则与文本一致):priority=0(默认):适合离线索引,仍分别受TEXT_MAX_INFLIGHT/IMAGE_MAX_INFLIGHTadmission control 约束。priority>0(建议在线请求用1):不会因 admission control 被拒绝,但仍会占用对应 text/image 的 inflight。- 文本服务端会优先处理高优先级文本请求;图片端不实现插队,顺序按请求到达处理即可。
GET /health会返回各自的limits、stats、cache_enabled等状态;GET /ready用于就绪探针。
7.1.1 POST /embed/text — 文本向量化
将文本列表转为 1024 维向量,用于语义搜索、文档索引等。
完整 curl 示例:
curl -X POST "http://localhost:6005/embed/text?normalize=true&priority=1" \
-H "Content-Type: application/json" \
-d '["芭比娃娃 儿童玩具", "纯棉T恤 短袖"]'
响应(JSON 数组,与输入一一对应):
[[0.01, -0.02, ...], [0.03, 0.01, ...], ...]
说明:
- 在线 query / 实时请求:显式传
priority=1 - 离线索引 / 批量回填:保持默认
priority=0即可 - 离线索引建议直接传数组,单次尽量聚合到 24 条文本。
- 当前 TEI 客户端按
TEI_MAX_CLIENT_BATCH_SIZE=24调优;超过该值会继续拆批,但推荐调用方主动分批。
7.1.2 POST /embed/image — 图片向量化
将图片 URL 或路径转为向量,用于以图搜图。
前置条件:cnclip 服务已启动(默认端口 51000)。若未启动,图片 embedding 服务启动会失败或请求返回错误。
完整 curl 示例:
curl -X POST "http://localhost:6008/embed/image?normalize=true&priority=1" \
-H "Content-Type: application/json" \
-d '["https://oss.essa.cn/98532128-cf8e-456c-9e30-6f2a5ea0c19f.jpg"]'
响应(JSON 数组,与输入一一对应):
[[0.01, -0.02, ...], [0.03, 0.01, ...], ...]
在线以图搜图等实时场景可传 priority=1;离线索引回填保持默认 priority=0。
离线图片向量化建议每次聚合 8 张图片 URL 后请求,避免长期逐张调用。
7.1.3 POST /embed/clip_text — CN-CLIP 文本多模态向量(与图片同空间)
将自然语言短语编码为向量,与 POST /embed/image 输出的图向量处于同一向量空间(Chinese-CLIP 文本塔 / 图塔),用于 以文搜图、与 ES image_embedding 对齐的 KNN 等。默认配置为 ViT-H-14,向量长度 1024(与 mappings/search_products.json 中 image_embedding.vector.dims 一致);若改为 ViT-L-14 则为 768 维,须同步索引映射与全量重索引。
curl 示例:
curl -X POST "http://localhost:6008/embed/clip_text?normalize=true&priority=1" \
-H "Content-Type: application/json" \
-d '["纯棉短袖", "street tee"]'
响应(JSON 数组,与输入一一对应):
[[0.01, -0.02, ...], [0.03, 0.01, ...], ...]
说明:与 /embed/image 共用图片侧限流与 IMAGE_MAX_INFLIGHT;Redis 缓存键 namespace 为 clip_text,与 TEI 文本缓存区分。
调用建议:离线批量构建图文检索索引时,建议每次聚合 24 条短文本。
7.1.4 GET /health — 健康检查
curl "http://localhost:6005/health"
curl "http://localhost:6008/health"
返回中会包含:
service_kind:text/image/allcache_enabled:text/image/clip_text Redis 缓存是否可用limits:当前 inflight limit、active、rejected_total 等stats:request_total、cache_hits、cache_misses、avg_latency_ms 等
7.1.5 GET /ready — 就绪检查
curl "http://localhost:6005/ready"
curl "http://localhost:6008/ready"
7.1.6 缓存与限流说明
- 文本与图片都会先查 Redis 向量缓存。
- Redis 中 value 仍是 BF16 bytes,读取后恢复成
float32返回。 - cache key 已区分
normalize=true/false,避免不同归一化策略命中同一条缓存。 - 当服务端发现请求是 full-cache-hit 时,会直接返回,不占用模型并发槽位。
- 当服务端发现超过
TEXT_MAX_INFLIGHT/IMAGE_MAX_INFLIGHT时,会直接拒绝,而不是无限排队。 - 其中
POST /embed/text的priority=0会按上面的 inflight 规则直接拒绝;priority>0不会被 admission 拒绝,但仍计入 inflight,并在服务端排队时优先于priority=0请求。 POST /embed/image的priority=0受IMAGE_MAX_INFLIGHT约束;priority>0不会被 admission 拒绝,但仍计入 inflight(无插队)。POST /embed/clip_text与/embed/image共用同一后端与IMAGE_MAX_INFLIGHT(计入图片侧并发)。
7.1.7 TEI 统一调优建议(主服务)
使用单套主服务即可同时兼顾:
- 在线 query 向量化(低延迟,常见
batch=1~4) - 索引构建向量化(高吞吐,常见
batch=24)
统一启动(主链路):
./scripts/start_tei_service.sh
./scripts/service_ctl.sh restart embedding
默认端口:
- TEI:
http://127.0.0.1:8080 - 文本向量服务(
/embed/text):http://127.0.0.1:6005 - 图片向量服务(
/embed/image、/embed/clip_text):http://127.0.0.1:6008
当前主 TEI 启动默认值(已按 T4/短文本场景调优):
TEI_MAX_BATCH_TOKENS=4096TEI_MAX_CLIENT_BATCH_SIZE=24TEI_DTYPE=float16
7.2 重排服务(Reranker)
- Base URL:
http://localhost:6007(可通过RERANKER_SERVICE_URL覆盖) - 启动:
./scripts/start_reranker.sh
说明:默认后端为 qwen3_vllm(Qwen/Qwen3-Reranker-0.6B),需要可用 GPU 显存。
补充:若切换到 jina_reranker_v3,在当前 Tesla T4 上建议使用:
dtype: float16batch_size: 64max_doc_length: 160max_query_length: 64sort_by_doc_length: true
原因:jina_reranker_v3 的 auto 在当前机器上会落到 bfloat16,性能明显差于 float16;而它的 listwise 架构在 T4 上对上下文长度更敏感,过大的 batch 会显著拉长延迟。
补充:docs 的请求大小与模型推理 batch size 解耦。即使一次传入 1000 条文档,服务端也会按 services.rerank.backends.qwen3_vllm.infer_batch_size 自动拆分。
7.2.1 POST /rerank — 结果重排
根据 query 与 doc 的相关性对文档列表重新打分排序。
请求体:
{
"query": "玩具 芭比",
"docs": [
"12PCS 6 Types of Dolls with Bottles",
"纯棉T恤 短袖 夏季"
],
"normalize": true
}
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
query |
string | Y | 搜索查询 |
docs |
array[string] | Y | 待重排的文档列表(单次最多由服务端配置限制) |
normalize |
boolean | N | 是否对分数做 sigmoid 归一化,默认 true |
响应:
{
"scores": [0.92, 0.15],
"meta": {
"service_elapsed_ms": 45.2,
"input_docs": 2,
"unique_docs": 2
}
}
完整 curl 示例:
curl -X POST "http://localhost:6007/rerank" \
-H "Content-Type: application/json" \
-d '{
"query": "玩具 芭比",
"docs": ["12PCS 6 Types of Dolls with Bottles", "纯棉T恤 短袖"],
"top_n":386,
"normalize": true
}'
7.2.2 GET /health — 健康检查
curl "http://localhost:6007/health"
7.3 翻译服务(Translation)
- Base URL:
http://localhost:6006(以config/config.yaml -> services.translation.service_url为准) - 启动:
./scripts/start_translator.sh
7.3.1 POST /translate — 文本翻译
支持 translator service 内所有已启用 capability,适用于商品名称、描述、query 等电商场景。当前可配置能力包括 qwen-mt、llm、deepl 以及本地模型 nllb-200-distilled-600m、opus-mt-zh-en、opus-mt-en-zh。
请求体(支持单条字符串或字符串列表):
{
"text": "商品名称",
"target_lang": "en",
"source_lang": "zh",
"model": "qwen-mt",
"scene": "sku_name"
}
也支持批量列表形式:
{
"text": ["商品名称1", "商品名称2"],
"target_lang": "en",
"source_lang": "zh",
"model": "qwen-mt",
"scene": "sku_name"
}
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
text |
string \ | string[] | Y |
target_lang |
string | Y | 目标语言:zh、en、ru 等 |
source_lang |
string | N | 源语言。云端模型可不传;nllb-200-distilled-600m 建议显式传入 |
model |
string | N | 已启用 capability 名称,如 qwen-mt、llm、deepl、nllb-200-distilled-600m、opus-mt-zh-en、opus-mt-en-zh |
scene |
string | N | 翻译场景参数,与 model 配套使用;当前标准值为 sku_name、ecommerce_search_query、general |
说明:
- 外部接口不接受
prompt;LLM prompt 由服务端按scene自动生成。 - 传入未定义的
scene或未启用的model会返回400。
SKU 名称场景选型建议:
- 批量 SKU 名称翻译,优先考虑本地大吞吐方案时,可使用
"model": "nllb-200-distilled-600m"(该模型"scene":参数无效)。 - 如果目标是更高质量,且可以接受更慢速度与额外 LLM API 费用,可使用
"model": "llm"+"scene": "sku_name"。 - 如果是en-zh互译、期待更高的速度,可以考虑
opus-mt-zh-en/opus-mt-en-zh。(质量未详细评测,一些文章说比blib-200-600m更好,但是我看了些case感觉要差不少)
实时翻译选型建议:
- 在线 query 翻译如果只是
en/zh互译,优先使用opus-mt-zh-en或opus-mt-en-zh。 - 如果涉及其他语言,或对质量要求高于本地轻量模型,优先考虑
deepl。 nllb-200-distilled-600m不建议作为在线 query 翻译默认方案;我们在Tesla T4上测到batch_size=1时,根据query长短,耗时大概在70-150ms之间。
Batch Size / 调用方式建议:
- 本接口支持
text: string[];离线或批量索引翻译时,应尽量合并请求,让底层 backend 发挥批处理能力。 - 对商品标题、标题片段、属性值等短文本,调用方建议按
8~16条/批聚合后再调用;这比大量batch=1并发更能发挥 GPU 吞吐。 nllb-200-distilled-600m在当前Tesla T4压测中,推荐配置是batch_size=16、max_new_tokens=64、attn_implementation=sdpa;继续升到batch_size=32虽可能提高吞吐,但 tail latency 会明显变差。- 在线 query 场景可直接把“单条请求”理解为
batch_size=1;更关注 request latency,而不是离线吞吐。 opus-mt-zh-en/opus-mt-en-zh当前生产配置也是batch_size=16,适合作为中英互译的低延迟本地默认值;若走在线单条调用,同样按batch_size=1理解即可。llm、qwen-mt、deepl也支持列表调用;如果是离线索引链路,仍建议优先合并成批,以减少 HTTP 往返和缓存探测开销。
响应:
{
"text": "商品名称",
"target_lang": "en",
"source_lang": "zh",
"translated_text": "Product name",
"status": "success",
"model": "qwen-mt",
"scene": "sku_name"
}
当请求为列表形式时,text 与 translated_text 均为等长数组:
{
"text": ["商品名称1", "商品名称2"],
"target_lang": "en",
"source_lang": "zh",
"translated_text": ["Product name 1", "Product name 2"],
"status": "success",
"model": "qwen-mt",
"scene": "sku_name"
}
失败语义(批量):当
text为列表时,如果其中某条翻译失败,对应位置返回null(即translated_text[i] = null),并保持数组长度与顺序不变;接口整体仍返回status="success",用于避免“部分失败”导致整批请求失败。实现提示(可忽略):服务端会尽可能使用底层 backend 的批量能力(若支持),否则自动拆分逐条翻译;无论采用哪种方式,上述批量契约保持一致。
完整 curl 示例:
中文 → 英文:
curl -X POST "http://localhost:6006/translate" \
-H "Content-Type: application/json" \
-d '{
"text": "商品名称",
"target_lang": "en",
"source_lang": "zh"
}'
俄文 → 英文:
curl -X POST "http://localhost:6006/translate" \
-H "Content-Type: application/json" \
-d '{
"text": "Название товара",
"target_lang": "en",
"source_lang": "ru"
}'
使用 DeepL 模型:
curl -X POST "http://localhost:6006/translate" \
-H "Content-Type: application/json" \
-d '{
"text": "商品名称",
"target_lang": "en",
"source_lang": "zh",
"model": "deepl"
}'
使用本地 OPUS 模型(中文 → 英文):
curl -X POST "http://localhost:6006/translate" \
-H "Content-Type: application/json" \
-d '{
"text": "蓝牙耳机",
"target_lang": "en",
"source_lang": "zh",
"model": "opus-mt-zh-en",
"scene": "sku_name"
}'
使用本地 NLLB 做 SKU 名称批量翻译:
curl -X POST "http://localhost:6006/translate" \
-H "Content-Type: application/json" \
-d '{
"text": ["商品名称1", "商品名称2", "商品名称3"],
"target_lang": "en",
"source_lang": "zh",
"model": "nllb-200-distilled-600m",
"scene": "sku_name"
}'
使用 LLM 做高质量 SKU 名称翻译:
curl -X POST "http://localhost:6006/translate" \
-H "Content-Type: application/json" \
-d '{
"text": "男士偏光飞行员太阳镜",
"target_lang": "en",
"source_lang": "zh",
"model": "llm",
"scene": "sku_name"
}'
7.3.2 GET /health — 健康检查
curl "http://localhost:6006/health"
典型响应:
{
"status": "healthy",
"service": "translation",
"default_model": "llm",
"default_scene": "general",
"available_models": ["qwen-mt", "llm", "opus-mt-zh-en"],
"enabled_capabilities": ["qwen-mt", "llm", "opus-mt-zh-en"],
"loaded_models": ["llm"]
}
7.4 内容理解字段生成(Indexer 服务内)
内容理解字段生成接口部署在 Indexer 服务(默认端口 6004)内,与「翻译、向量化」等独立端口微服务并列,供采用微服务组合方式的 indexer 调用。
- Base URL: Indexer 服务地址,如
http://localhost:6004 - 路径:
POST /indexer/enrich-content - 说明: 根据商品标题批量生成
qanchors、enriched_attributes、enriched_tags、enriched_taxonomy_attributes,用于拼装 ES 文档。支持通过enrichment_scopes选择执行generic/category_taxonomy,并通过category_taxonomy_profile选择对应大类的 taxonomy prompt/profile;默认执行generic + category_taxonomy(apparel)。当前支持的 taxonomy profile 包括apparel、3c、bags、pet_supplies、electronics、outdoor、home_appliances、home_living、wigs、beauty、accessories、toys、shoes、sports、others。所有 profile 的 taxonomy 输出都统一返回zh+en,category_taxonomy_profile只决定字段集合。内部使用大模型(需配置DASHSCOPE_API_KEY),支持按单条进行 Redis 缓存;单次最多 50 条,但推荐常态请求控制在20条左右**。内部大模型处理批次按20条拆分。
请求/响应格式、示例及错误码见 -05-索引接口(Indexer)。