# Embeddings 模块 **请求示例**见 `docs/QUICKSTART.md` §3.3。 **专项文档**: - `../docs/TEI_SERVICE说明文档.md` - `../docs/CNCLIP_SERVICE说明文档.md` **请求日志串联(reqid / uid)**:统一实现在仓库根目录的 `request_log_context.py`(勿放到 `utils/` 下,以免 `.venv-embedding` 因 `utils/__init__.py` 拉取数据库依赖)。Uvicorn 日志配置见 `config/uvicorn_embedding_logging.json`。 --- 这个目录是一个完整的“向量化模块”,包含: - **HTTP 客户端**:`text_encoder.py` / `image_encoder.py`(供搜索/索引模块调用) - **本地模型实现**:`text_embedding_sentence_transformers.py` / `clip_model.py` - **clip-as-service 客户端**:`clip_as_service_encoder.py`(图片向量,推荐) - **向量化服务(FastAPI)**:`server.py` - **统一配置**:`config.py` - **接口契约**:`protocols.ImageEncoderProtocol`(`encode_image_urls` + `encode_clip_texts`;本地 CN-CLIP 与 clip-as-service 均实现) 说明:历史上的云端 embedding 试验实现(DashScope)已从主仓库移除。当前默认部署为**文本服务 6005** 与**图片服务 6008** 两条独立链路;`all` 模式仅作为单进程调试入口。 ### 文本向量后端(默认) - 6005 文本向量服务默认后端:`TEI`(Text Embeddings Inference) - 默认模型:`Qwen/Qwen3-Embedding-0.6B` - 后端配置来源:`config/config.yaml -> services.embedding.backend/backends` - 环境变量覆盖:`EMBEDDING_BACKEND`、`TEI_BASE_URL`、`TEI_TIMEOUT_SEC` ### 服务接口 - 文本服务(默认 `6005`) - `POST /embed/text` - 请求体:`["文本1", "文本2", ...]` - 可选 query 参数:`normalize=true|false`、`priority=0|1` - 返回:`[[...], [...], ...]` - 健康接口:`GET /health`、`GET /ready` - 图片服务(默认 `6008`) - `POST /embed/image`:图片 URL 或本地路径 - `POST /embed/clip_text`:自然语言(CN-CLIP 文本塔,与 `/embed/image` 同向量空间;勿传 `http://` 图 URL) - 请求体:`["...", ...]` 字符串数组 - 可选 query 参数:`normalize=true|false`、`priority=0|1` - 返回:`[[...], [...], ...]` - 健康接口:`GET /health`、`GET /ready` ### Redis 向量缓存 - Value 格式没有变化,仍然是 **BF16 bytes**: - 写入:`float32 -> BF16 -> bytes` - 读取:`bytes -> BF16 -> float32` - 现在是**双层缓存**: - client 侧:`text_encoder.py` / `image_encoder.py` - service 侧:`server.py` - 当前主 key 格式: - 文本(TEI):`embedding:embed:norm{0|1}:{text}` - 图片:`embedding:image:embed:norm{0|1}:{url_or_path}` - CN-CLIP 文本:`embedding:clip_text:clip_mm:norm{0|1}:{text}` - 当前实现不再兼容历史 key 规则,只保留这一套格式,减少代码路径和缓存歧义。 ### 压力隔离与拒绝策略 - 文本与图片各自有独立 admission control: - `TEXT_MAX_INFLIGHT` - `IMAGE_MAX_INFLIGHT` - 图片服务可以配置得比文本更严格。 - 请求若是 full-cache-hit,会在服务端直接返回,不占用模型并发槽位。 - 超过处理能力时直接拒绝,比无限排队更稳定。 - 文本服务支持 `priority`: - `priority=0`(默认,适合离线索引)仍受 `TEXT_MAX_INFLIGHT` 限制,超限直接返回 overload。 - `priority>0`(建议在线 query 用 `1`)不会因 admission control 被拒绝,但仍会计入 inflight。 - 文本服务内部使用双队列调度,处理时会优先消费高优先级请求,避免在线请求长期排在离线批量任务后面。 - 图片服务同样支持 `priority`(语义与文本一致,按 `IMAGE_MAX_INFLIGHT` 计数;不做队列插队,仅 admission 规则不同)。 ### 图片向量:clip-as-service(推荐) 默认使用 `third-party/clip-as-service` 的 Jina CLIP 服务生成图片向量。 1. **安装 embedding 专用环境**(首次使用): ```bash ./scripts/setup_embedding_venv.sh ``` 如需使用本地 `local_st` 文本后端,再执行: ```bash INSTALL_LOCAL_ST=1 ./scripts/setup_embedding_venv.sh ``` 2. **启动 CN-CLIP 服务**(独立 gRPC 服务,默认端口 51000,详见 `../docs/CNCLIP_SERVICE说明文档.md`): ```bash ./scripts/start_cnclip_service.sh ``` 3. **配置**(`embeddings/config.py` 或环境变量): - `USE_CLIP_AS_SERVICE=true`(默认) - `CLIP_AS_SERVICE_SERVER=grpc://127.0.0.1:51000` - `CLIP_AS_SERVICE_MODEL_NAME=CN-CLIP/ViT-L-14` - `scripts/start_cnclip_service.sh` 默认会读取同一个 `CLIP_AS_SERVICE_MODEL_NAME`,也可用 `CNCLIP_MODEL_NAME` 或 `--model-name` 临时覆盖 ### 性能与压测(沿用仓库脚本) - 接口级压测(与 `perf_reports/2026-03-12/matrix_report/` 等方法一致):`scripts/perf_api_benchmark.py` - 示例:`python scripts/perf_api_benchmark.py --scenario embed_text --duration 30 --concurrency 20` - 文本/图片向量可带 `priority`(与线上 admission 语义一致):`--embed-text-priority 1`、`--embed-image-priority 1` - 自定义请求模板:`--cases-file scripts/perf_cases.json.example` - 历史矩阵结果与说明见 `perf_reports/2026-03-12/matrix_report/summary.md`。 ### 启动服务 使用仓库脚本启动: ```bash # GPU(需 nvidia-container-toolkit) TEI_DEVICE=cuda ./scripts/start_tei_service.sh # CPU TEI_DEVICE=cpu ./scripts/start_tei_service.sh ./scripts/start_embedding_text_service.sh ./scripts/start_embedding_image_service.sh ``` ### 修改配置 编辑 `embeddings/config.py`: - `PORT`: `all` 模式单进程端口(默认 6005) - `TEXT_MODEL_ID`, `TEXT_DEVICE`, `TEXT_BATCH_SIZE`, `TEXT_NORMALIZE_EMBEDDINGS` - `IMAGE_NORMALIZE_EMBEDDINGS`(默认 true) - `USE_CLIP_AS_SERVICE`, `CLIP_AS_SERVICE_SERVER`, `CLIP_AS_SERVICE_MODEL_NAME`:图片向量(clip-as-service) - `IMAGE_MODEL_NAME`, `IMAGE_DEVICE`:本地 CN-CLIP(当 `USE_CLIP_AS_SERVICE=false` 时) - TEI 相关:`TEI_DEVICE`、`TEI_VERSION`、`TEI_MAX_BATCH_TOKENS`、`TEI_MAX_CLIENT_BATCH_SIZE`、`TEI_HEALTH_TIMEOUT_SEC` - 分流/限流相关: - `EMBEDDING_SERVICE_KIND=all|text|image` - `EMBEDDING_TEXT_PORT` - `EMBEDDING_IMAGE_PORT` - `TEXT_MAX_INFLIGHT` - `IMAGE_MAX_INFLIGHT`