Name Last Update
..
README.md Loading commit data...
__init__.py Loading commit data...
bf16.py Loading commit data...
cache_keys.py Loading commit data...
clip_as_service_encoder.py Loading commit data...
clip_model.py Loading commit data...
config.py Loading commit data...
image_encoder.py Loading commit data...
protocols.py Loading commit data...
redis_embedding_cache.py Loading commit data...
server.py Loading commit data...
text_embedding_sentence_transformers.py Loading commit data...
text_embedding_tei.py Loading commit data...
text_encoder.py Loading commit data...

README.md

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 格式(model_nameCONFIG.MULTIMODAL_MODEL_NAME,与 services.embedding.image_backends 一致):
    • 文本(TEI):embedding:embed:norm{0|1}:{text_or_sha256_digest}
    • CN-CLIP 图片:embedding:image:embed:{model_name}:txt:norm{0|1}:{url_or_sha256_digest}
    • CN-CLIP 文本塔:embedding:clip_text:embed:{model_name}:img:norm{0|1}:{text_or_sha256_digest}
  • 尾部负载:长度 ≤ CACHE_KEY_RAW_BODY_MAX_CHARS(默认 256,见 embeddings/cache_keys.py)用原文;更长用 h:sha256:<hex>(TEI 与多模态共用同一辅助函数)。
  • 切换多模态模型会自然换 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-H-14(与 config/config.yamlservices.embedding.image_backends 一致;换 ViT-L 时为 768 维,须同步改 ES 映射)
    • 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