README.md 6.15 KB

Embeddings 模块

请求示例docs/QUICKSTART.md §3.3。 专项文档

  • ../docs/TEI_SERVICE说明文档.md
  • ../docs/CNCLIP_SERVICE说明文档.md

请求日志串联(reqid / uid):统一实现在仓库根目录的 request_log_context.py(勿放到 utils/ 下,以免 .venv-embeddingutils/__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.ImageEncoderProtocolencode_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_BACKENDTEI_BASE_URLTEI_TIMEOUT_SEC

服务接口

  • 文本服务(默认 6005
    • POST /embed/text
    • 请求体:["文本1", "文本2", ...]
    • 可选 query 参数:normalize=true|falsepriority=0|1
    • 返回:[[...], [...], ...]
    • 健康接口:GET /healthGET /ready
  • 图片服务(默认 6008
    • POST /embed/image:图片 URL 或本地路径
    • POST /embed/clip_text:自然语言(CN-CLIP 文本塔,与 /embed/image 同向量空间;勿传 http:// 图 URL)
    • 请求体:["...", ...] 字符串数组
    • 可选 query 参数:normalize=true|falsepriority=0|1
    • 返回:[[...], [...], ...]
    • 健康接口:GET /healthGET /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 专用环境(首次使用):

    ./scripts/setup_embedding_venv.sh
    

    如需使用本地 local_st 文本后端,再执行:

    INSTALL_LOCAL_ST=1 ./scripts/setup_embedding_venv.sh
    
  2. 启动 CN-CLIP 服务(独立 gRPC 服务,默认端口 51000,详见 ../docs/CNCLIP_SERVICE说明文档.md):

    ./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

启动服务

使用仓库脚本启动:

# 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_DEVICETEI_VERSIONTEI_MAX_BATCH_TOKENSTEI_MAX_CLIENT_BATCH_SIZETEI_HEALTH_TIMEOUT_SEC
  • 分流/限流相关:
    • EMBEDDING_SERVICE_KIND=all|text|image
    • EMBEDDING_TEXT_PORT
    • EMBEDDING_IMAGE_PORT
    • TEXT_MAX_INFLIGHT
    • IMAGE_MAX_INFLIGHT