feat: evaluate pinned local embedding models on CPU

This commit is contained in:
2026-10-16 09:11:33 +08:00
parent 1c9b351507
commit cf4e65bb9d
11 changed files with 647 additions and 1 deletions
+5
View File
@@ -28,3 +28,8 @@ FastAPI + Pydantic
## 安全边界
当前无认证与权限控制,仅供本机开发;正式部署前须补充登录鉴权、接口限流、数据库迁移、密钥管理、日志脱敏、CORS 收敛和 HTTPS。
## 本地 Embedding 评估(T07 准备)
`app/services/embedding.py` 定义固定模型身份、可替换编码接口及可选 CPU Provider;模型库按需导入,普通 API 启动不加载权重。`evaluation/local_embeddings.py` 在独立进程中验证真实模型向量和 token 预算,并测量已标注合成样本的资源/排序结果;不读取或写入业务数据库。当前尚未把向量接入检索 API,详见 [本地模型评估](LOCAL_EMBEDDING_EVALUATION.md)。
+7
View File
@@ -22,3 +22,10 @@
## ADR-007 显式迁移与旧数据保留
状态:分支实现,待合并请求审阅。以 Alembic 取代应用启动时的 `create_all`。基础迁移接管旧知识表,新增字段和表通过增量迁移完成;不推测旧数据采集时间。旧审核结论缺少完整记录时保留原快照并转待审核。迁移回滚需先备份,新增历史与审核元数据无法通过降级完整保留。
## ADR-011 本地 Embedding 独立评估与空间身份
状态:T07 本地评估分支,待审阅。用户选择先评估本地开源模型与资源;采用固定 revision 的 BGE small/base 中文模型做 CPU 实测,保持可替换 Provider、CLS/L2 与查询指令配置。模型、维度、修订及编码配置形成独立空间身份,禁止后续混用。
评估环境与默认后端分开,不在 API 启动时下载或加载模型。当前合成小样本只验证流程与资源,实际数据集 SHA、计时和模型身份可复核;默认模型仍须经过真实已审核问题集评测。详见 [本地模型评估](LOCAL_EMBEDDING_EVALUATION.md)。
+77
View File
@@ -0,0 +1,77 @@
# T07:本地 Embedding 与 CPU 资源评估
本阶段从 `dev` 独立开发,交付可替换 Provider 和可复现的本地 CPU 评估工具。它不依赖待审 PR #6/#7/#8 的接口或数据库迁移;后续向量检索集成再组合这些基础。普通后端启动及普通自动化测试均不导入 PyTorch、不加载模型,也不要求模型下载。
## 固定配置与边界
| CLI 名称 | 官方模型 | 固定 revision | 维度 | Token 上限 | 权重格式 |
|---|---|---|---:|---:|---|
| small | BAAI/bge-small-zh-v1.5 | `7999e1d3359715c523056ef9478215996d62a620` | 512 | 512 | Safetensors |
| base | BAAI/bge-base-zh-v1.5 | `f03589ceff5aac7111bd60cfc7d497ca17ecac65` | 768 | 512 | PyTorch,仅权重读取 |
两者使用 CLS 输出、L2 归一化、CPU FP32;查询添加官方检索指令,正文不添加该指令。`EmbeddingSpec` 冻结模型/revision/维度/token 上限/查询指令/实现版本/权重格式,由规范 JSON 生成 `space_id`。不同空间必须分开保存和查询;目前只提供身份契约,数据库隔离约束尚待向量阶段实现。
模型仓库均标注 MIT。基础版该修订只提供 `pytorch_model.bin`,显式使用 Transformers 的 `weights_only=True` 读取;不会自动回退未知格式或开启远程模型代码。公开模型下载使用 `token=False`,不要求或读取用户保存的 Hugging Face 凭据。默认只用本机缓存,CLI `--download` 才允许下载固定修订。
`LocalEmbeddingProvider` 按批处理,默认 batch=8、CPU 线程=2;显式限制 batch 1–32、线程 1–4。输入先按真实 tokenizer 计数,包含查询指令和特殊 token;超过模型上限明确报错,不静默截断。输出检查数量、维度、有限数值和 L2 范数。字符切分长度不等于 token 数,后续接入 chunks 时须据此重新检查。
## 输入与指标
项目当前资料台账只有未核验的占位行,没有可用于正式选型的领域数据。本阶段自带 `backend/evaluation/synthetic_zh.json`,含 12 条明确标注“合成测试”的示例文本及 10 个问题,ID/相关文档标注在运行前固定。这些句子不描述那拉提真实事实,不写入应用数据库。
评估保存输入文件 SHA-256、模型完整配置与空间 ID、运行库版本、实际命中 ID/分数、命中率、Recall@3 和 MRR@3。排序采用归一化向量内积,同分按文档 ID;数值不是正确率或置信度。命中率检查首位相关文档;Recall@k 为前 k 命中相关文档数/标注相关文档总数;MRR@k 为首个相关命中的倒数,未命中为 0。
每项计时先按同一输入形状预热一次,然后记录 5 次及中位数:12 条语料编码、10 个查询批量编码、单个查询、8 条长文本批量编码。长文本均为相同的合成句子重复形成,360 字符/362 token,仅测试资源。包含分词、补齐、前向、归一化和结果转换;不包含网络、数据库、HTTP 或整个 RAG 延迟。初始化时间单独记录,可能包含缓存检查/下载与首次加载,不用于模型推理速度比较。Linux 峰值 RSS 是整个独立进程高水位,包含解释器、运行库和模型,不能当作仅权重大小。
## 本机实测
运行环境:Linux、Python 3.11.17、4 个逻辑 CPU、内存总计约 9.7 GiB,检查时可用约 5.0 GiB;GPU 驱动不可用,本轮仅用 CPU。PyTorch `2.14.1+cpu`、Transformers `5.20.0`、huggingface-hub `2.2.0`、NumPy `2.4.6`;每个模型用独立进程测量,线程 2、batch 8、每项 5 次。未记录用户名、主机名或本机个人路径。
输入文件 SHA-256:`9f4762a10dc1502b871c84ccedf9fbbdbd93067b8318476a77c78aa14789b243`。
| 模型 | 12 条正文批编码中位数 | 10 个查询批编码中位数 | 单查询中位数 | 8 条长文批编码中位数 | 峰值进程 RSS | 合成 Hit@1 / Recall@3 / MRR@3 |
|---|---:|---:|---:|---:|---:|---|
| small | 98.708 ms | 72.877 ms | 8.927 ms | 457.944 ms | 531.2 MiB | 0.90 / 0.90 / 0.90 |
| base | 582.315 ms | 416.287 ms | 52.912 ms | 3016.157 ms | 865.5 MiB | 1.00 / 1.00 / 1.00 |
两个模型在该负载下都能使用本机 CPU。small 在合成问题 q05(出处可靠性)把住宿条目 d07 排在首位,目标资料审核条目 d06 未进入前三;base 将 d06 排首位。这里保留失败结果,不修改数据以提高分数。两个模型的相似度分布不同,不能共用固定分数阈值。
建议:资源优先的后端开发验证可先使用 small,保留 base 作对照。正式默认模型暂不冻结,先在已核验语料与独立问题集上比较相关性、无依据情形和实际端到端延迟。当前未测 GPU、并发服务、最大 token 负载或完整索引构建。
这些是合成小样本的功能与资源结果,不是项目正式实验分数。不能据此断言真实文旅问答质量或生产尾延迟。应先用资料负责人核验后的语料及独立问题集复测,再固定默认模型;不能通过修改测试题迎合已观察的排名。
## 复现(Linux,仓库根目录)
可使用 `uv` 创建独立 Python 3.11 环境;或以等价 venv/pip 命令安装。依赖独立于 `requirements.txt`,不把 GPU 依赖或模型加入默认 API 启动流程。
```bash
task_eval_root=$(git rev-parse --absolute-git-dir)
test -x "$task_eval_root/embedding-eval-venv/bin/python" || \
uv venv --python 3.11 "$task_eval_root/embedding-eval-venv"
uv pip install --python "$task_eval_root/embedding-eval-venv/bin/python" \
--index-url https://download.pytorch.org/whl/cpu torch==2.14.1+cpu
uv pip install --python "$task_eval_root/embedding-eval-venv/bin/python" \
-r backend/requirements-embedding-cpu.txt
export HF_HUB_DISABLE_TELEMETRY=1 HF_HUB_DISABLE_IMPLICIT_TOKEN=1
export HF_HUB_DISABLE_PROGRESS_BARS=1 TOKENIZERS_PARALLELISM=false
export HF_HUB_DISABLE_XET=1
(
cd backend
"$task_eval_root/embedding-eval-venv/bin/python" -m evaluation.local_embeddings \
--model small --download --cache-dir "$task_eval_root/embedding-model-cache" \
--output "$task_eval_root/embedding-evaluation/small.json"
"$task_eval_root/embedding-eval-venv/bin/python" -m evaluation.local_embeddings \
--model base --download --cache-dir "$task_eval_root/embedding-model-cache" \
--output "$task_eval_root/embedding-evaluation/base.json"
)
```
后续离线复跑去掉 `--download`。可用 `--dataset` 指定同结构数据,文档/问题各最多 1000 条、文件最多 2MB;拒绝重复 ID、未知或重复的相关文档标注。报告不含输入文本,但实际问题/标签可能仍敏感,原始报告、运行输出、环境及模型缓存都应只留在本机 Git 元数据目录,不提交。参数错误或模型失败不会生成伪造的成功结果。
普通后端验证仍是在 `backend/` 执行 `ruff check .`、`ruff format --check .`、`pytest -q`。轻量测试验证模型身份、非法输出、资源参数、token 拒绝、输入标注及手算排序指标,不需要模型包或联网;真实模型执行由上述独立 CLI 验证。
## 下一步
将 Provider 接入已发布的文本版本,完成 pgvector 存储与严格空间隔离、向量检索及 RRF,再使用真实审核语料评测。模型编码耗时应在发布锁外运行,发布前重新核对目录/语料版本;过期或失败时保留旧版本。当前没有新增向量数据库字段、检索 API 或论文结论。
依据:[BGE small 官方模型说明](https://huggingface.co/BAAI/bge-small-zh-v1.5)、[BGE base 官方文件](https://huggingface.co/BAAI/bge-base-zh-v1.5/tree/f03589ceff5aac7111bd60cfc7d497ca17ecac65)、[Transformers 模型加载参数](https://huggingface.co/docs/transformers/main_classes/model#transformers.PreTrainedModel.from_pretrained)、[PyTorch CPU 安装](https://pytorch.org/get-started/locally/)、[Hugging Face 固定修订下载](https://huggingface.co/docs/huggingface_hub/guides/download)。
+11
View File
@@ -44,3 +44,14 @@
- 覆盖:新库迁移、已有基础表接管、重复升级、阶段 2 降级后基础正文保留、ORM 与迁移结构一致、审核前置条件、正文/来源/文档变更后重新审核、历史快照、软删除引用保护、筛选与分页、并发写入冲突、跨域预检、真实 HTTP 与服务重启持久化。
所有测试正文、来源和审核人均为占位数据,临时数据库不入库。当前问答仍是占位接口,未开展论文对照实验。Issue、合并请求和最终批准结论须补入 Gitea 后按团队规则归档。
## 2026-10-16 T07:本地 Embedding 与资源评估
- 用户选择先评估本地开源模型与本机资源;从最新 `dev` 独立创建 `feat/backend-local-embedding-evaluation`,不依赖仍待审的 #6/#7/#8。
- 实现不在普通启动流程加载模型的 Provider、固定 revision 与空间身份、维度/有限数/L2 校验、真实 token 上限拒绝及独立 CPU 评估 CLI。可选依赖和模型缓存与默认后端环境分开。
- 固定 BGE small/base 中文模型,CPU 线程 2、batch 8、各输入形状预热一次后重复 5 次。单查询中位数分别 8.927/52.912 ms,独立进程峰值 RSS 531.2/865.5 MiB;两者实际运行、向量校验与超限拒绝通过。
- 项目资料台账目前只有占位行,本轮采用事先固定的 12 文本/10 问题合成样本,仅验证流程。small 的合成 Hit@1/Recall@3/MRR@3 为 0.90,base 为 1.00;不是实际文旅质量或论文结论,保留 small 的错误案例,不据此冻结正式默认模型。
- 固定配置、完整指标定义、输入哈希、复现命令和限制见 [本地模型评估](LOCAL_EMBEDDING_EVALUATION.md)。原始运行报告、权重、虚拟环境只保存在本机 Git 元数据目录,不入库。
- 向量数据库/空间隔离、索引构建、向量/RRF 检索、真实已核验问题集和浏览器/部署验收仍待后续推进;本轮没有把这些标记为完成。
- 本独立分支实际验证:`ruff check .`、`ruff format --check .` 通过;`pytest -q` **44 passed**,包含当前 dev 的 PostgreSQL/HTTP 基线与新增轻量契约/指标用例。small/base 另由独立模型环境真实执行;可选依赖在新建空环境中完成 CPU wheel 安装与后续依赖解析验证。先前 #7/#8 的 70/91 项结果属于各自分支,不混同为本独立分支的测试计数。