通过海报相似度探索跨语言作品与英文主记录的关联,提供 TMDB 海报接入、版本化向量检索、单图上传检索和本地只读对照页。
现有固定开发样本包含 100 部电影、100 张英语参考和 698 张查询。SigLIP2 的 Top-1 为
636/698(91.12%),Recall@5 为 692/698(99.14%)。这是既有库内实验结果,
构图全部未人工核验,不能作为业务准确率或自动接受阈值。库外、规模评估和公司记录写回尚未实现。
本地进度与验收证据见 docs/project-scope.md;doc/、docs/ 不随 Git 分发。
需要 Python 3.12 和 uv。在项目根目录执行:
uv python install 3.12
make install
make dev
服务监听 127.0.0.1:8000,make start 不启用自动重载。启动和默认测试无需凭据、数据库或模型。
Makefile 优先使用 .tools/uv/bin/uv,否则使用 PATH 中的 uv。
上传检索需要已准备的模型和参考库,用 make dev-model 或 make start-model 启动。
普通 make dev/start/check 使用基础依赖;之后测试上传时重新使用带 -model 的命令。
| 地址 | 用途 |
|---|---|
| 首页 | 上传检索及离线海报对照 |
| 健康检查 | 进程存活,不检查外部服务 |
| Swagger UI | API 文档 |
| OpenAPI | API 描述 |
make check
检查包含锁文件、Ruff、格式、mypy 和 pytest;默认测试不访问 TMDB、下载模型或连接真实数据库。
已有依赖且需要保留当前模型运行环境时,可用
UV_CACHE_DIR=.uv-cache UV_OFFLINE=true UV_NO_SYNC=true make check。
真实 PostgreSQL 测试需设置目标库为 keyart_match 的 P2_TEST_DATABASE_URL,运行
uv run --locked pytest tests/integration/test_embedding_postgres.py;测试使用独立临时 schema。
按需将 .env.example 复制为 .env;环境变量优先,空值使用默认值,修改后重启。
真实凭据仅放在 .env 或运行环境,不打印配置对象和连接串。
| 变量 | 默认值 / 用途 |
|---|---|
KEYART_APP_NAME | Keyart Match,API 文档标题 |
KEYART_DOCS_ENABLED | true,启用 Swagger UI、ReDoc 和 OpenAPI |
KEYART_DATABASE_URL | 空;向量命令及上传使用,目标库必须为 keyart_match |
KEYART_REVIEW_MANIFEST_PATH | data/tmdb-100-movies/manifest.json |
KEYART_REVIEW_REPORT_DIR | artifacts/siglip2-100-movies-2026-09-11;上传读取 build.json,对照页另需 queries.json |
KEYART_MATCH_MODEL_DIR | models/siglip2-so400m-naflex;须匹配构建报告中的空间与设备 |
TMDB_API_READ_ACCESS_TOKEN | 空;下载使用的 Bearer token,优先使用 |
TMDB_API_KEY | 空;未填写 Read Access Token 时的替代认证 |
清单、报告和模型必须配套;默认路径指向现有固定样本,新实验应使用独立目录并同步配置。
数据库连接串格式为 postgresql://<user>:<encoded-password>@<host>:<port>/keyart_match;
密码中的特殊字符需 URL 编码,.env 文件权限建议为 600。
配置 TMDB 凭据后显式执行,服务不会自动采集:
uv run --locked keyart-ingest \
--batch examples/tmdb-100-movies.json \
--output data/tmdb-100-movies
examples/tmdb-small-batch.json 是 3 部电影的较小示例,使用独立输出目录。
自定义批次格式如下,tv 表示整剧,不接受季或集:
{
"works": [{"media_type": "movie", "tmdb_id": 157336}],
"query_languages": ["zh", "ja", "ko", "es"],
"image_size": "w500"
}
作品类型与 ID 组合必须唯一;查询语言为不重复、非 en 的两位小写代码;尺寸支持 w342/w500。
英语海报用作参考。选图规则 rating_votes_area_path_v1:仅取 posters,按来源路径去重,
再按评分、票数、像素面积降序及路径升序,每部每语种取第一张;缺图不补选。
同路径元数据冲突时该作品失败,目标外语言与未使用海报保留元数据和原因。
产物为 manifest.json、report.json 和按 SHA-256 命名的 images/reference/、images/query/。
后续仅使用完成下载且最终用途为 reference/query 的记录,不扫描目录代替清单。
参考与查询来源路径或字节重复时,查询改为 unused;已下载文件与来源关系保留。
下载最多 20 MiB,仅接受完整解码的 JPEG/PNG;校验后原子写入。网络错误、429 和 5xx 最多尝试 3 次。
凭据只发往 TMDB API。重复命令可恢复:已完成元数据冻结,有效图片核对哈希后跳过,失败项重试。
同目录不允许并发运行或改变批次参数。complete 不保证每部都有参考或构图已核验;
构图默认 unreviewed,需人工标为 similar/different/uncertain,不能由 TMDB ID 推断。
模型依赖、数据库初始化和模型下载均需显式执行。以下以 Apple MPS 为例,其他设备使用 --device cpu:
uv sync --locked --extra model
uv run --locked keyart-embed init-db
uv run --locked --extra model keyart-embed prepare-model \
--device mps --model-dir models/siglip2-so400m-naflex
uv run --locked --extra model keyart-embed build \
--manifest data/tmdb-100-movies/manifest.json \
--model-dir models/siglip2-so400m-naflex \
--report artifacts/siglip2-run/build.json
uv run --locked --extra model keyart-embed query \
--manifest data/tmdb-100-movies/manifest.json \
--model-dir models/siglip2-so400m-naflex \
--corpus-id '<build 报告中的 corpus_id>' \
--top-k 5 --report artifacts/siglip2-run/queries.json
使用这份新报告启动页面时,将 KEYART_REVIEW_REPORT_DIR 改为 artifacts/siglip2-run。
仅 init-db 创建专库、扩展和表;项目表位于 keyart_match schema,扩展位于 public,
结构版本为 1,未知版本拒绝运行。已存在的数据保留,不回退到其他业务库。
固定模型为 google/siglip2-so400m-patch16-naflex,revision、文件校验和预处理定义见
src/keyart_match/embeddings/siglip2.py。完整下载约 4.54 GB,推理只加载视觉塔;
完整解码、EXIF 方向修正、RGB、官方慢版处理器、保持长宽比、576 patches,
输出 1152 维池化特征并 L2 归一化。CPU/MPS 均为 float32、eager、单图推理。
模型、权重、预处理、设备和运行库版本形成 embedding_space_id,完整参考集合与空间形成 corpus_id。
设备在准备时固定,默认 CPU;更换设备需使用新模型目录并重建参考库,不会自动回退。
build/query 和上传只读本地模型,校验不符时拒绝编码,不自动下载;同维度不同空间也不能混检。
进程内复用同一文件版本的完整校验结果;配置、权重或空间标记变化时重新校验,并检查校验与加载期间的变化。
首次校验仍读取完整权重,后续状态检查不重复计算未变化文件的 SHA;文件版本缓存不等于每次逐字节重验。
构建核验全部英语参考的用途、路径、下载状态、尺寸与 SHA,按 (embedding_space_id, sha256)
复用向量并保留来源关系。逐张提交,可恢复;全部参考齐全才标为 ready,查询再次验证完整性。
查询图与目标参考的来源路径或字节重复时拒绝检索,查询向量不入库。
排序使用精确余弦相似度,每部作品取最高分证据,稳定排序后返回 Top-K;没有 ANN 索引。
top-k 为 1–20;分数仅用于排序,不是正确概率。
报告放在批次和模型目录外,逐项原子更新;同一报告路径的并发构建或查询会明确拒绝。
构建重跑复用向量,查询重跑重新编码。
接入与向量 CLI 退出码:0 成功,1 逐项失败,2 输入/配置/读写错误,130 中断。
接入中的缺图与去重排除不导致非零退出码,仍需检查报告。
keyart-rerank 只读取既有清单、构建和查询报告,不连接数据库,不重新编码 SigLIP2。
Qwen 需要同时启用 model 与 rerank;准备命令会下载约 4.3 GB 官方固定文件,评估不会自动下载:
uv sync --locked --extra model --extra rerank
uv run --locked --extra model --extra rerank keyart-rerank prepare-model \
--model-dir models/qwen3-vl-reranker-2b
uv run --locked --extra model --extra rerank keyart-rerank evaluate \
--manifest data/tmdb-100-movies/manifest.json \
--build-report artifacts/siglip2-100-movies-2026-09-11/build.json \
--query-report artifacts/siglip2-100-movies-2026-09-11/queries.json \
--model-dir models/qwen3-vl-reranker-2b \
--report artifacts/rerank-run/evaluation.json \
--top-k 5 --device mps --dtype float16 --max-pixels 384000
首次可用 --limit 20 冒烟,之后去掉限制、保持参数与报告路径继续。报告以 partial/complete
区分范围,完成项经校验后复用。模型、设备、精度、像素预算、窗口、标题模式或输入变化时使用新报告。
当前评估协议为 v2(schema_version=2);旧 v1 报告保留作历史证据,新评估使用新报告路径。
--image-only 移除候选标题,供消融;CPU 使用显式 --device cpu --dtype float32。
模型只接收查询图、候选图和可选候选标题,图片元数据会清除;真值 ID/标题、路径、原排名与分数不送入评分。
目标是同一作品,续集和翻拍不算同一部,Top-K 外不按真值补候选。模型初始化、设备或固定文件校验失败
立即以退出码 2 终止,保留已完成进度,修复环境后可继续。普通候选评分失败使所选窗口回退原排序,
仍保留在分母;恢复复用这些已记录回退,不自动重试。原查询失败与重排失败分别统计。
前三名对照从同批逐对评分派生,只受查询图及原前三候选失败影响;两个窗口分别报告回退数,分母保持一致。
报告包含救回、退化、净变化、语言/作品分组和耗时,MRR 使用原查询的完整候选窗口。
开发样本结果不能当作新作品或库外准确率。
退出码:0 无记录失败,1 原查询失败或重排回退,2 输入/模型/文件错误,130 中断。
配套清单、构建报告和模型就绪后,运行 make start-model,在首页选择或拖入海报。
一次一张 JPEG/PNG,最多 20 MiB、2000 万像素;Top-K 为 1–20,默认 5。
接口为 POST /v1/matches(multipart 字段 image、top_k),就绪状态为 GET /v1/matches/status。
返回候选、证据海报、分数、第一第二名分差、版本和耗时;相同参考字节会标记 exact_reference_match。
本机单进程并发 1;忙时返回 429。超出大小/像素上限返回 413,不支持的媒体/图片格式返回 415,
损坏图片或无效字段返回 422,模型、数据库或参考库未就绪返回 503。临时文件在请求结束后清理。
上传正文须在 30 秒内接收完成,超时返回 408 并释放处理名额;该期限不限制模型推理。
服务启动不加载模型或连接数据库;状态请求校验就绪情况,首次上传才加载模型。
取消等待不终止已经运行的模型推理,处理名额保持占用直至后台工作结束。
公网认证、多进程和批量上传不在当前范围内。
对照页只读同目录的 build.json、queries.json 与配套清单,支持筛选、放大和查看版本。
它不需要数据库或模型权重,也不触发采集、编码或标注写回;因此历史 DINOv2 报告仍可查看。
报告缺失、未完成或不一致时,数据接口返回 503;修改报告后刷新页面。
构图标签来自清单和报告,显示相似度与分差不表示已经达到业务关联标准。
数据、图片、模型、实验产物、本地文档与凭据不提交 Git。分支使用 codex/ 前缀,提交前运行 make check。
通过海报相似度探索跨语言作品与英文主记录的关联,提供 TMDB 海报接入、版本化向量检索、单图上传检索和本地只读对照页。
现有固定开发样本包含 100 部电影、100 张英语参考和 698 张查询。SigLIP2 的 Top-1 为
636/698(91.12%),Recall@5 为 692/698(99.14%)。这是既有库内实验结果,
构图全部未人工核验,不能作为业务准确率或自动接受阈值。库外、规模评估和公司记录写回尚未实现。
本地进度与验收证据见 docs/project-scope.md;doc/、docs/ 不随 Git 分发。
需要 Python 3.12 和 uv。在项目根目录执行:
uv python install 3.12
make install
make dev
服务监听 127.0.0.1:8000,make start 不启用自动重载。启动和默认测试无需凭据、数据库或模型。
Makefile 优先使用 .tools/uv/bin/uv,否则使用 PATH 中的 uv。
上传检索需要已准备的模型和参考库,用 make dev-model 或 make start-model 启动。
普通 make dev/start/check 使用基础依赖;之后测试上传时重新使用带 -model 的命令。
| 地址 | 用途 |
|---|---|
| 首页 | 上传检索及离线海报对照 |
| 健康检查 | 进程存活,不检查外部服务 |
| Swagger UI | API 文档 |
| OpenAPI | API 描述 |
make check
检查包含锁文件、Ruff、格式、mypy 和 pytest;默认测试不访问 TMDB、下载模型或连接真实数据库。
已有依赖且需要保留当前模型运行环境时,可用
UV_CACHE_DIR=.uv-cache UV_OFFLINE=true UV_NO_SYNC=true make check。
真实 PostgreSQL 测试需设置目标库为 keyart_match 的 P2_TEST_DATABASE_URL,运行
uv run --locked pytest tests/integration/test_embedding_postgres.py;测试使用独立临时 schema。
按需将 .env.example 复制为 .env;环境变量优先,空值使用默认值,修改后重启。
真实凭据仅放在 .env 或运行环境,不打印配置对象和连接串。
| 变量 | 默认值 / 用途 |
|---|---|
KEYART_APP_NAME | Keyart Match,API 文档标题 |
KEYART_DOCS_ENABLED | true,启用 Swagger UI、ReDoc 和 OpenAPI |
KEYART_DATABASE_URL | 空;向量命令及上传使用,目标库必须为 keyart_match |
KEYART_REVIEW_MANIFEST_PATH | data/tmdb-100-movies/manifest.json |
KEYART_REVIEW_REPORT_DIR | artifacts/siglip2-100-movies-2026-09-11;上传读取 build.json,对照页另需 queries.json |
KEYART_MATCH_MODEL_DIR | models/siglip2-so400m-naflex;须匹配构建报告中的空间与设备 |
TMDB_API_READ_ACCESS_TOKEN | 空;下载使用的 Bearer token,优先使用 |
TMDB_API_KEY | 空;未填写 Read Access Token 时的替代认证 |
清单、报告和模型必须配套;默认路径指向现有固定样本,新实验应使用独立目录并同步配置。
数据库连接串格式为 postgresql://<user>:<encoded-password>@<host>:<port>/keyart_match;
密码中的特殊字符需 URL 编码,.env 文件权限建议为 600。
配置 TMDB 凭据后显式执行,服务不会自动采集:
uv run --locked keyart-ingest \
--batch examples/tmdb-100-movies.json \
--output data/tmdb-100-movies
examples/tmdb-small-batch.json 是 3 部电影的较小示例,使用独立输出目录。
自定义批次格式如下,tv 表示整剧,不接受季或集:
{
"works": [{"media_type": "movie", "tmdb_id": 157336}],
"query_languages": ["zh", "ja", "ko", "es"],
"image_size": "w500"
}
作品类型与 ID 组合必须唯一;查询语言为不重复、非 en 的两位小写代码;尺寸支持 w342/w500。
英语海报用作参考。选图规则 rating_votes_area_path_v1:仅取 posters,按来源路径去重,
再按评分、票数、像素面积降序及路径升序,每部每语种取第一张;缺图不补选。
同路径元数据冲突时该作品失败,目标外语言与未使用海报保留元数据和原因。
产物为 manifest.json、report.json 和按 SHA-256 命名的 images/reference/、images/query/。
后续仅使用完成下载且最终用途为 reference/query 的记录,不扫描目录代替清单。
参考与查询来源路径或字节重复时,查询改为 unused;已下载文件与来源关系保留。
下载最多 20 MiB,仅接受完整解码的 JPEG/PNG;校验后原子写入。网络错误、429 和 5xx 最多尝试 3 次。
凭据只发往 TMDB API。重复命令可恢复:已完成元数据冻结,有效图片核对哈希后跳过,失败项重试。
同目录不允许并发运行或改变批次参数。complete 不保证每部都有参考或构图已核验;
构图默认 unreviewed,需人工标为 similar/different/uncertain,不能由 TMDB ID 推断。
模型依赖、数据库初始化和模型下载均需显式执行。以下以 Apple MPS 为例,其他设备使用 --device cpu:
uv sync --locked --extra model
uv run --locked keyart-embed init-db
uv run --locked --extra model keyart-embed prepare-model \
--device mps --model-dir models/siglip2-so400m-naflex
uv run --locked --extra model keyart-embed build \
--manifest data/tmdb-100-movies/manifest.json \
--model-dir models/siglip2-so400m-naflex \
--report artifacts/siglip2-run/build.json
uv run --locked --extra model keyart-embed query \
--manifest data/tmdb-100-movies/manifest.json \
--model-dir models/siglip2-so400m-naflex \
--corpus-id '<build 报告中的 corpus_id>' \
--top-k 5 --report artifacts/siglip2-run/queries.json
使用这份新报告启动页面时,将 KEYART_REVIEW_REPORT_DIR 改为 artifacts/siglip2-run。
仅 init-db 创建专库、扩展和表;项目表位于 keyart_match schema,扩展位于 public,
结构版本为 1,未知版本拒绝运行。已存在的数据保留,不回退到其他业务库。
固定模型为 google/siglip2-so400m-patch16-naflex,revision、文件校验和预处理定义见
src/keyart_match/embeddings/siglip2.py。完整下载约 4.54 GB,推理只加载视觉塔;
完整解码、EXIF 方向修正、RGB、官方慢版处理器、保持长宽比、576 patches,
输出 1152 维池化特征并 L2 归一化。CPU/MPS 均为 float32、eager、单图推理。
模型、权重、预处理、设备和运行库版本形成 embedding_space_id,完整参考集合与空间形成 corpus_id。
设备在准备时固定,默认 CPU;更换设备需使用新模型目录并重建参考库,不会自动回退。
build/query 和上传只读本地模型,校验不符时拒绝编码,不自动下载;同维度不同空间也不能混检。
进程内复用同一文件版本的完整校验结果;配置、权重或空间标记变化时重新校验,并检查校验与加载期间的变化。
首次校验仍读取完整权重,后续状态检查不重复计算未变化文件的 SHA;文件版本缓存不等于每次逐字节重验。
构建核验全部英语参考的用途、路径、下载状态、尺寸与 SHA,按 (embedding_space_id, sha256)
复用向量并保留来源关系。逐张提交,可恢复;全部参考齐全才标为 ready,查询再次验证完整性。
查询图与目标参考的来源路径或字节重复时拒绝检索,查询向量不入库。
排序使用精确余弦相似度,每部作品取最高分证据,稳定排序后返回 Top-K;没有 ANN 索引。
top-k 为 1–20;分数仅用于排序,不是正确概率。
报告放在批次和模型目录外,逐项原子更新;同一报告路径的并发构建或查询会明确拒绝。
构建重跑复用向量,查询重跑重新编码。
接入与向量 CLI 退出码:0 成功,1 逐项失败,2 输入/配置/读写错误,130 中断。
接入中的缺图与去重排除不导致非零退出码,仍需检查报告。
keyart-rerank 只读取既有清单、构建和查询报告,不连接数据库,不重新编码 SigLIP2。
Qwen 需要同时启用 model 与 rerank;准备命令会下载约 4.3 GB 官方固定文件,评估不会自动下载:
uv sync --locked --extra model --extra rerank
uv run --locked --extra model --extra rerank keyart-rerank prepare-model \
--model-dir models/qwen3-vl-reranker-2b
uv run --locked --extra model --extra rerank keyart-rerank evaluate \
--manifest data/tmdb-100-movies/manifest.json \
--build-report artifacts/siglip2-100-movies-2026-09-11/build.json \
--query-report artifacts/siglip2-100-movies-2026-09-11/queries.json \
--model-dir models/qwen3-vl-reranker-2b \
--report artifacts/rerank-run/evaluation.json \
--top-k 5 --device mps --dtype float16 --max-pixels 384000
首次可用 --limit 20 冒烟,之后去掉限制、保持参数与报告路径继续。报告以 partial/complete
区分范围,完成项经校验后复用。模型、设备、精度、像素预算、窗口、标题模式或输入变化时使用新报告。
当前评估协议为 v2(schema_version=2);旧 v1 报告保留作历史证据,新评估使用新报告路径。
--image-only 移除候选标题,供消融;CPU 使用显式 --device cpu --dtype float32。
模型只接收查询图、候选图和可选候选标题,图片元数据会清除;真值 ID/标题、路径、原排名与分数不送入评分。
目标是同一作品,续集和翻拍不算同一部,Top-K 外不按真值补候选。模型初始化、设备或固定文件校验失败
立即以退出码 2 终止,保留已完成进度,修复环境后可继续。普通候选评分失败使所选窗口回退原排序,
仍保留在分母;恢复复用这些已记录回退,不自动重试。原查询失败与重排失败分别统计。
前三名对照从同批逐对评分派生,只受查询图及原前三候选失败影响;两个窗口分别报告回退数,分母保持一致。
报告包含救回、退化、净变化、语言/作品分组和耗时,MRR 使用原查询的完整候选窗口。
开发样本结果不能当作新作品或库外准确率。
退出码:0 无记录失败,1 原查询失败或重排回退,2 输入/模型/文件错误,130 中断。
配套清单、构建报告和模型就绪后,运行 make start-model,在首页选择或拖入海报。
一次一张 JPEG/PNG,最多 20 MiB、2000 万像素;Top-K 为 1–20,默认 5。
接口为 POST /v1/matches(multipart 字段 image、top_k),就绪状态为 GET /v1/matches/status。
返回候选、证据海报、分数、第一第二名分差、版本和耗时;相同参考字节会标记 exact_reference_match。
本机单进程并发 1;忙时返回 429。超出大小/像素上限返回 413,不支持的媒体/图片格式返回 415,
损坏图片或无效字段返回 422,模型、数据库或参考库未就绪返回 503。临时文件在请求结束后清理。
上传正文须在 30 秒内接收完成,超时返回 408 并释放处理名额;该期限不限制模型推理。
服务启动不加载模型或连接数据库;状态请求校验就绪情况,首次上传才加载模型。
取消等待不终止已经运行的模型推理,处理名额保持占用直至后台工作结束。
公网认证、多进程和批量上传不在当前范围内。
对照页只读同目录的 build.json、queries.json 与配套清单,支持筛选、放大和查看版本。
它不需要数据库或模型权重,也不触发采集、编码或标注写回;因此历史 DINOv2 报告仍可查看。
报告缺失、未完成或不一致时,数据接口返回 503;修改报告后刷新页面。
构图标签来自清单和报告,显示相似度与分差不表示已经达到业务关联标准。
数据、图片、模型、实验产物、本地文档与凭据不提交 Git。分支使用 codex/ 前缀,提交前运行 make check。