# 模块扩展规范(向量化 / 重排 可插拔设计) 本文档定义**向量化(embedding)**与**重排(rerank)**模块的扩展规范,保证新增模型/推理引擎时框架统一、配置统一、可插拔。新增 Qwen3-Reranker-0.6B(vLLM)等模块时需遵循本规范。 **相关文档**: - 调用方(Provider 选择、HTTP 客户端):[PROVIDER_ARCHITECTURE.md](./PROVIDER_ARCHITECTURE.md) - 向量化使用说明:[embeddings/README.md](../embeddings/README.md)、[向量化模块和API说明文档.md](./向量化模块和API说明文档.md) --- ## 1. 设计原则 | 原则 | 说明 | |------|------| | **接口契约** | 所有同类型后端实现同一协议(Protocol),调用方只依赖协议不依赖具体实现。 | | **单一配置源** | 能力类型、后端类型、后端参数均来自 `config/config.yaml` 的 `services` 块,环境变量可覆盖。 | | **服务与后端分离** | **调用方**通过 Provider(如 `HttpRerankProvider`)访问**服务**;**服务内部**通过后端实现(如 BGE、Qwen3-vLLM)完成推理。新增“提供者”时区分:是新增一种**调用方式**(新 Provider)还是新增一种**推理实现**(新 Backend)。 | | **可插拔后端** | 重排/向量化服务在启动时根据配置加载一个后端;新增后端 = 实现协议 + 在配置与工厂中注册,不改服务入口代码。 | --- ## 2. 配置体系(统一结构) ### 2.1 配置来源与优先级 - **主配置**:`config/config.yaml` 下的 `services.` - **覆盖**:环境变量(如 `RERANKER_SERVICE_URL`、`RERANK_BACKEND`)> config 文件 - **解析**:`config/services_config.py` 提供 `get_*_config()`,各模块从该处读取,避免散落多处。 ### 2.2 能力块通用结构 每种能力(translation / embedding / rerank)在 `services` 下结构一致: ```yaml services: : provider: "http" # 调用方使用的提供者:http | direct | vllm 等 base_url: "http://..." # 对外服务 URL(provider=http 时) providers: http: { base_url: "...", ... } direct: { ... } vllm: { ... } # 以下为「服务内部后端」配置(仅当本能力由本仓库启动的服务承载时使用) backend: "bge" # 可选:服务内加载的后端类型 backends: bge: { model_name: "...", batch_size: 64, ... } qwen3_vllm: { model_name: "Qwen/Qwen3-Reranker-0.6B", ... } ``` - **provider**:调用方(搜索 API、索引等)如何访问该能力(如 HTTP 调 `base_url`)。 - **backend / backends**:当该能力由本仓库内的服务进程提供时,该进程内应加载哪个后端及参数(如 reranker 服务内用 BGE 还是 Qwen3-vLLM)。 --- ## 3. 重排(Rerank)模块规范 ### 3.1 调用链 - **调用方**:`search/rerank_client.py` → `create_rerank_provider()` → `HttpRerankProvider.rerank(query, docs, timeout_sec)` - **协议**:HTTP `POST /rerank`,请求体 `{ "query": str, "docs": [str] }`,响应体 `{ "scores": [float], "meta": dict }`,scores 与 docs 一一对应。 - **服务实现**:`reranker/server.py`(FastAPI)在启动时加载一个**重排后端**,对 `/rerank` 的请求用该后端计算分数。 因此: - **新增一种“调用方式”**(如 gRPC):在 `providers/rerank.py` 增加新 Provider 类,并在 `create_rerank_provider()` 中按 `provider` 选择。 - **新增一种“推理实现”**(如 Qwen3-vLLM):在 reranker 服务内实现**重排后端协议**并注册,服务通过配置选择后端。 ### 3.2 重排后端协议(服务内) 所有在 `reranker` 服务内加载的后端必须实现以下接口(与当前 `BGEReranker` 一致): ```python # 行为契约(不强制继承,实现以下方法即可) class RerankBackendProtocol(Protocol): def score_with_meta( self, query: str, docs: List[str], normalize: bool = True, ) -> Tuple[List[float], Dict[str, Any]]: """ 输入: - query: 搜索查询字符串 - docs: 文档列表,与返回的 scores 一一对应 - normalize: 是否对分数做归一化(如 sigmoid) 输出: - scores: 与 docs 等长的分数列表,顺序一致 - meta: 至少含 input_docs, usable_docs, unique_docs, elapsed_ms 等,供日志与调试 """ ... ``` - **顺序**:返回的 `scores[i]` 必须对应 `docs[i]`。 - **空/无效**:对无法打分的 doc 可填 0.0,并在 meta 中说明。 - **去重**:后端可对 docs 去重再推理以省算力,但返回的 scores 必须按原始 docs 顺序与长度还原。 ### 3.3 重排服务配置项(建议) 在 `config/config.yaml` 的 `services.rerank` 下建议结构(与现有 `rerank` 顶层配置区分:顶层为搜索侧融合参数,此处为服务/后端配置): ```yaml services: rerank: provider: "http" base_url: "http://127.0.0.1:6007" providers: http: base_url: "http://127.0.0.1:6007" service_url: "http://127.0.0.1:6007/rerank" # 服务内后端(reranker 进程启动时读取) backend: "bge" # bge | qwen3_vllm backends: bge: model_name: "BAAI/bge-reranker-v2-m3" device: null use_fp16: true batch_size: 64 max_length: 512 cache_dir: "./model_cache" enable_warmup: true qwen3_vllm: model_name: "Qwen/Qwen3-Reranker-0.6B" engine: "vllm" max_model_len: 8192 tensor_parallel_size: 1 gpu_memory_utilization: 0.8 instruction: "Given a web search query, retrieve relevant passages that answer the query" ``` - 环境变量示例:`RERANK_BACKEND=qwen3_vllm`、`RERANKER_SERVICE_URL=http://127.0.0.1:6007`。 ### 3.4 重排后端目录与注册 - **推荐目录**:`reranker/backends/` - `reranker/backends/__init__.py`:导出 `get_rerank_backend(name, config) -> 实现 RerankBackendProtocol 的实例` - `reranker/backends/bge.py`:现有 BGE 逻辑迁移或封装为 `BGERerankerBackend` - `reranker/backends/qwen3_vllm.py`:新增 Qwen3-Reranker-0.6B + vLLM 实现 - **服务启动**:`reranker/server.py` 在 `startup` 中读取 `services.rerank.backend` 与 `services.rerank.backends.`,调用 `get_rerank_backend(backend, cfg)` 得到实例,再对外提供同一 `/rerank` API。 ### 3.5 重排 HTTP API 契约(不变) 无论后端是 BGE 还是 Qwen3-vLLM,对外接口保持一致,便于调用方与运维统一: - **POST /rerank** - Request: `{ "query": string, "docs": [string], "normalize": optional bool }` - Response: `{ "scores": [float], "meta": object }` - **GET /health** - Response: `{ "status": "ok"|"unavailable", "model_loaded": bool, "model": string, "backend": string }` --- ## 4. 向量化(Embedding)模块规范 ### 4.1 调用链 - **调用方**:通过 `providers.create_embedding_provider()` 得到 HTTP 客户端,请求 `POST /embed/text`、`POST /embed/image`。 - **服务实现**:`embeddings/server.py` 在启动时按配置加载**文本后端**与**图片后端**,二者可独立选择。 ### 4.2 向量化后端协议(服务内) - **文本**:与当前 `BgeTextModel` 一致,需支持 `encode_batch(texts, batch_size, device) -> List[ndarray]`,元素与 `texts` 一一对应,失败可为 None。 - **图片**:已定义 `embeddings/protocols.ImageEncoderProtocol`: - `encode_image_urls(urls: List[str], batch_size: Optional[int]) -> List[Optional[np.ndarray]]` - 与 `urls` 等长,失败位置为 None。 新增文本/图片后端时实现对应协议即可;服务通过配置选择后端(如 `USE_CLIP_AS_SERVICE` 选 clip-as-service 或本地 CN-CLIP)。 ### 4.3 向量化配置(现有与扩展) - **Provider/URL**:`config/config.yaml` → `services.embedding`,环境变量 `EMBEDDING_SERVICE_URL`。 - **服务内**:`embeddings/config.py` 中已有 `TEXT_*`、`IMAGE_*`、`USE_CLIP_AS_SERVICE`、`CLIP_AS_SERVICE_SERVER`;若未来支持多种文本/图像后端,建议在 `services.embedding.backend` / `services.embedding.backends` 中统一,与重排结构对齐。 --- ## 5. 新增后端清单(以 Qwen3-Reranker-0.6B + vLLM 为例) 按本规范新增「重排后端」Qwen3-Reranker-0.6B(vLLM 推理)时,建议步骤: 1. **实现协议** - 在 `reranker/backends/qwen3_vllm.py` 中实现类(如 `Qwen3VLLMReranker`),提供 `score_with_meta(query, docs, normalize) -> (scores, meta)`。 - 推理逻辑参考 [Qwen3-Reranker-0.6B](https://huggingface.co/Qwen/Qwen3-Reranker-0.6B) 的 vLLM 用法(format_instruction、process_inputs、compute_logits、yes/no token 等),输出与 `docs` 等长且顺序一致的 scores。 2. **配置** - 在 `config/config.yaml` 的 `services.rerank.backends` 下增加 `qwen3_vllm` 块(model_name、engine、max_model_len、tensor_parallel_size、gpu_memory_utilization、instruction 等)。 - 在 `config/services_config.py` 或 reranker 专用 config 中增加对 `backend` / `backends` 的读取;环境变量支持 `RERANK_BACKEND=qwen3_vllm`。 3. **注册** - 在 `reranker/backends/__init__.py` 的 `get_rerank_backend(name, config)` 中增加 `"qwen3_vllm"` 分支,实例化 `Qwen3VLLMReranker` 并传入 config。 4. **服务启动** - 若尚未重构:可暂时在 `reranker/server.py` 中根据 `RERANK_BACKEND` 或 config 选择加载 `BGEReranker` 或 `Qwen3VLLMReranker`。 - 若已引入 `get_rerank_backend()`:`reranker/server.py` 启动时统一调用 `get_rerank_backend(backend_name, backend_cfg)` 得到实例。 5. **调用方** - 无需修改:`providers/rerank.py` 仍为 HTTP,`search/rerank_client.py` 仍调用同一 `/rerank` 接口;仅部署时启动使用 Qwen3-vLLM 后端的 reranker 服务即可。 6. **文档与依赖** - 在 `reranker/README.md` 或 `docs/` 中说明 Qwen3-vLLM 的依赖(vllm>=0.8.5、transformers 等)、显存建议、与 BGE 的对比。 - 若 vLLM 为可选依赖,在 `requirements_ml.txt` 或可选 extra 中声明。 --- ## 6. 小结表 | 层次 | 配置键 | 重排 | 向量化(文本/图) | |------|--------|------|-------------------| | 调用方 | `services..provider` | http | http | | 调用方 | `services..providers.http.base_url` | 6007 | 6005 | | 服务内 | `services..backend` | bge / qwen3_vllm | (当前在 embeddings/config.py) | | 服务内 | `services..backends.` | 模型名、batch、vLLM 参数等 | 模型名、device 等 | | 协议 | 重排 | `score_with_meta(query, docs, normalize)` | — | | 协议 | 向量化 | — | 文本: encode_batch;图: ImageEncoderProtocol | 遵循上述规范后,新增 Qwen3-Reranker-0.6B 或其它重排/向量化后端时,只需实现协议、在配置与工厂中注册,即可与现有 BGE/CLIP 等并列切换,保持框架统一与可插拔。 --- ## 7. 与现有配置文件的兼容说明 - **reranker**:当前 `reranker/config.py` 中 `RerankerConfig`(PORT、MODEL_NAME、BATCH_SIZE 等)仅被 BGE 服务使用。扩展多后端时,建议: - 保留该文件作为**默认/兜底**(仅当未配置 `services.rerank.backend` 时使用),或 - 将 BGE 的默认值迁移到 `config.yaml` 的 `services.rerank.backends.bge`,`reranker/config.py` 只读环境变量与 YAML,不再硬编码模型名。 - **embeddings**:`embeddings/config.py` 的 `EmbeddingConfig` 已包含文本/图片及 clip-as-service 开关,与 `services.embedding` 的 URL 分离(URL 由 `services_config` 管)。后续若增加多种文本/图像后端,可同样在 `services.embedding.backends` 中增加条目,与重排对齐。 - **环境变量**:所有能力均支持通过环境变量覆盖(如 `RERANKER_SERVICE_URL`、`RERANK_BACKEND`、`EMBEDDING_SERVICE_URL`),便于部署与多环境。