fix: rebase vector retrieval on current docs
This commit is contained in:
@@ -74,4 +74,6 @@ export HF_HUB_DISABLE_XET=1
|
||||
|
||||
将 Provider 接入已发布的文本版本,完成 pgvector 存储与严格空间隔离、向量检索及 RRF,再使用真实审核语料评测。模型编码耗时应在发布锁外运行,发布前重新核对目录/语料版本;过期或失败时保留旧版本。当前没有新增向量数据库字段、检索 API 或论文结论。
|
||||
|
||||
以上描述 PR #9 独立评估阶段的范围;后续向量存储与精确检索集成另见 [VECTOR_API.md](VECTOR_API.md),不改变本页已记录的合成评估结果。
|
||||
|
||||
依据:[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)。
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# T07 向量快照、发布与精确检索
|
||||
|
||||
本分支 `feat/backend-vector-retrieval` 组合待审 #8 的文本版本与 #9 的固定版本 CPU Provider,继承 #7/#6。合并到 `dev` 前须按依赖审阅;不自行批准或合并。双方阶段文档均保留,独立阶段差异从组合基线 `bd0b738` 起查看。
|
||||
|
||||
交付 pgvector 存储、空间约束、独立发布、精确余弦检索与历史。关键词 `POST /api/retrieval` 保持原请求/分数/条目粒度;向量使用新的 `POST /api/retrieval/vector`,粒度为 chunk。本阶段尚未实现 RRF、ANN、RAG、持久化后台任务或正式领域评测。
|
||||
|
||||
## 配置与迁移
|
||||
|
||||
执行 `alembic upgrade head` 到 `0006_vectors`。迁移增加 `embedding_spaces`、`vector_versions`、`chunk_vectors`、`vector_state` 和 `vector_publications`,以及 chunks 的复合唯一约束。保留账号、目录、原文版本及既有检索日志,不预置模型或向量。
|
||||
|
||||
扩展类型/函数/距离算子显式引用 `public.vector`,业务表仍放在连接的当前 Schema,不把 public 加入测试搜索路径。已有 vector 扩展须位于 public;其他安装位置会明确报错,迁移不会移动共享扩展。新数据库可先由有权限的数据库管理员执行 `CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA public`。
|
||||
|
||||
默认 `EMBEDDING_ENABLED=false`,普通 API 启动不导入 PyTorch 或加载权重。模型相关请求返回 503,不回退占位向量或伪造空结果;关键词和管理元数据接口可继续使用。启用前按 [本地评估说明](LOCAL_EMBEDDING_EVALUATION.md) 安装独立 CPU 环境、缓存固定修订;该运行环境还需安装 `backend/requirements.txt` 的 API 依赖。
|
||||
|
||||
| 变量 | 默认值 | 作用 |
|
||||
|---|---|---|
|
||||
| `EMBEDDING_ENABLED` | false | 显式启用本地编码 |
|
||||
| `EMBEDDING_MODEL` | small | 仅 small/base;完整修订、维度等由固定 Spec 决定 |
|
||||
| `EMBEDDING_CACHE_DIR` | 未设置 | 固定模型缓存目录;空值使用库默认缓存 |
|
||||
| `EMBEDDING_BATCH_SIZE` | 8 | 1–32 |
|
||||
| `EMBEDDING_THREADS` | 2 | 1–4 个 CPU 线程 |
|
||||
|
||||
开发资源优先暂用 small,正式模型仍待已核验领域资料/问题集评测。API 始终只从本机固定修订缓存读取,禁止在请求中下载权重,不接收模型路径、任意仓库名或用户向量。CPU Provider 首次使用才加载,单进程同时只允许一个编码调用,繁忙立即返回 503;当前建议单 worker 本机运行,不能据此宣称已实现跨进程队列或生产并发容量。
|
||||
|
||||
Linux 仓库根目录示例(先完成模型准备及数据库迁移;本机 Cookie/Origin 配置仍按认证说明设置):
|
||||
|
||||
```bash
|
||||
task_vector_root=$(git rev-parse --absolute-git-dir)
|
||||
uv pip install --python "$task_vector_root/embedding-eval-venv/bin/python" \
|
||||
-r backend/requirements.txt
|
||||
export EMBEDDING_ENABLED=true EMBEDDING_MODEL=small
|
||||
export EMBEDDING_CACHE_DIR="$task_vector_root/embedding-model-cache"
|
||||
export HF_HUB_OFFLINE=1 HF_HUB_DISABLE_TELEMETRY=1 HF_HUB_DISABLE_IMPLICIT_TOKEN=1
|
||||
export TOKENIZERS_PARALLELISM=false
|
||||
cd backend
|
||||
"$task_vector_root/embedding-eval-venv/bin/python" -m uvicorn app.main:app --host 127.0.0.1
|
||||
```
|
||||
|
||||
环境、模型权重和实际日志只留本机,不提交。普通 API 环境不自动增加 PyTorch 依赖。
|
||||
|
||||
## 构建与发布协议
|
||||
|
||||
1. 通过 `/api/indexes` 构建并发布当前有效审核语料的文本版本。建议开发先用 `chunk_size=200, overlap=20`;实际 tokenizer 仍须检查,字符数不保证 token 数。
|
||||
2. 管理员向 `POST /api/vector-indexes` 提交 `{"text_index_version_id":"<已发布文本版本 UUID>"}`。服务仅接受当前有效的文本发布版本;整份快照最多 2000 chunks,超限返回 503,不截断语料。
|
||||
3. 服务短暂锁住目录/文本状态,复核实际审核语料指纹、原文窗口、偏移、哈希、出处和完整数量;复制输入后提交并释放事务。模型加载与正文编码全部在锁外运行。
|
||||
4. 编码成功且向量数量/维度/有限数/L2 范数通过后,再取得同一状态锁,重新校验文本代数、目录修订、当前指针、语料指纹及实际 chunks。变化则 409,整批不入库。成功只保存 ready 向量版本,不自动发布。
|
||||
5. 管理员向 `POST /api/vector-indexes/{id}/publish` 提交 `{"expected_generation":0}`。向量代数独立于文本代数;原子切换当前指针、前后版本状态和发布历史。旧代数、过期文本或不完整向量集均拒绝。相同当前版本和当前代数为幂等读取。
|
||||
|
||||
上述构建同步执行,没有后台任务 ID 或自动重试。超过模型 token 上限返回 422,应重新切分并发布文本,再重建;不会静默截断。编码不可用/繁忙为 503;数据库约束或版本竞争为 409。失败不会改写旧指针或留下部分向量版本。空的有效审核语料允许生成/发布 0 chunks 的版本;随后检索如实返回 `no_evidence`。
|
||||
|
||||
目录变化会使既有文本和向量版本过期;文本切换即使内容相同也要求对应新文本版本的向量。旧指针和日志保留为历史,公开检索对过期状态返回 409,不继续使用旧审核依据。切换模型配置后,若当前空间不一致,也须重新构建/发布相应空间或恢复匹配的运行配置。
|
||||
|
||||
## 数据库空间隔离
|
||||
|
||||
`space_id` 为固定 Spec 的 SHA-256,包含模型名、完整 revision、维度、token 上限、查询指令、编码实现(CLS/L2/CPU FP32)及权重格式。同维度的不同修订/指令/配置仍是不同空间。
|
||||
|
||||
数据库同时约束:
|
||||
|
||||
- 版本的 `(space_id, dimension)` 必须引用同一 EmbeddingSpace。
|
||||
- 每条向量的 `(version_id, text_index_version_id, space_id, dimension)` 必须引用同一向量版本。
|
||||
- `(chunk_id, text_index_version_id)` 必须引用对应文本版本中的 chunk。
|
||||
- `public.vector_dims` 必须等于声明维度;`public.vector_norm` 须在 `0.9999–1.0001`,pgvector 拒绝非有限元素。
|
||||
|
||||
使用无固定维度的 vector 列容纳独立空间,查询显式限定版本、空间、文本版本和维度,然后使用余弦距离。当前为有限语料精确扫描,没有 HNSW/IVFFlat;模型空间和向量发布均不由客户端参数任意指定。
|
||||
|
||||
## 接口与字段交接
|
||||
|
||||
`/api/vector-indexes` 下所有读写要求 admin;写入沿用当前 Cookie、CSRF 和明确 Origin。元数据不要求加载模型。分页使用 `{items,total,page,page_size}`,`page_size` 最大 100。
|
||||
|
||||
| 方法与路径 | 请求/用途 | 响应 |
|
||||
|---|---|---|
|
||||
| POST `/api/vector-indexes` | `text_index_version_id` | 201,VectorVersion |
|
||||
| GET `/api/vector-indexes` | page/page_size | 版本分页 |
|
||||
| GET `/api/vector-indexes/{id}` | UUID | VectorVersion,缺失 404 |
|
||||
| GET `/api/vector-indexes/active` | 当前元数据 | generation/text_generation/catalog_revision/is_current/active_version |
|
||||
| GET `/api/vector-indexes/spaces` | page/page_size | 空间 id/dimension/spec |
|
||||
| POST `/api/vector-indexes/{id}/publish` | expected_generation | 当前向量元数据 |
|
||||
| GET `/api/vector-indexes/publications` | page/page_size | 代数、前后向量版本、actor_id、UTC 时间 |
|
||||
| POST `/api/retrieval/vector` | 下方请求 | VectorRetrievalResponse |
|
||||
|
||||
VectorVersion 字段:`id/text_index_version_id/space_id/dimension/chunk_count/status/created_by/created_at/published_at`,状态为 ready/published/superseded;时间统一 UTC ISO 8601。发布历史的 `version_id` 是向量版本,不能与文本发布历史混用。
|
||||
|
||||
公开检索请求示例:
|
||||
|
||||
```json
|
||||
{"query":"待检索问题","mode":"vector","top_k":5,"category":"交通"}
|
||||
```
|
||||
|
||||
`mode` 可省略,固定为 vector;query 1–500 字符,top_k 1–20,category 可省略。未知字段拒绝。流程在查询编码前后均复核当前发布/审核状态和完整向量集;编码时不持有目录发布锁,期间任何发布代数变化都会返回 409,重试使用新快照。
|
||||
|
||||
响应记录:`run_id/query/mode/status/top_k/category/vector_version_id/text_index_version_id/generation/text_generation/corpus_fingerprint/corpus_size/total_hits/results/elapsed_ms/created_at/config`。`config` 固定 scorer=`pgvector-cosine-exact-v1`、ranking_unit=`chunk`,并保存完整空间 Spec。
|
||||
|
||||
每个 result 沿用关键词出处字段,再加 `chunk_id/chunk_ordinal`;snippet 为完整原文 chunk,snippet_start/end 是原正文的 Unicode 字符偏移(左闭右开),matched_terms 为空数组。score 为 `1 - cosine_distance`,不是正确率或置信度,也未设领域无依据阈值。按实际距离、knowledge_id、chunk_ordinal、chunk_id 排序;同一知识可出现多个 chunks,不能把结果数量当作命中的知识数。
|
||||
|
||||
`corpus_size/total_hits` 为分类筛选后的候选 chunk 数,不是超过置信阈值的数量;corpus_fingerprint 是整个已发布文本语料指纹,分类另行保存。耗时包括两次审核/快照检查、查询编码(首次可含模型加载)、SQL 距离排序与片段生成,不含最终日志提交及网络。不同于关键词基线的条目粒度,正式对照前必须统一评测单位。
|
||||
|
||||
成功和零候选均保存 `retrieval_runs` 不可变快照。既有历史接口现在返回 keyword/vector 判别联合,仍限 admin;不改写过去结果,也不因历史可读取就代表资料仍有效。前端调用层已同步 `services/vectors.ts` 与历史联合类型,页面和浏览器仍待接入验收。
|
||||
|
||||
## 回滚与验证
|
||||
|
||||
备份后 `alembic downgrade 0005_chunk_indexes` 删除本阶段空间、向量、向量状态和发布历史,保留文本 chunks/发布、账号、知识及所有检索结果快照。切回对应旧版后端前须处理其历史接口只认识 keyword 响应的兼容性;重升后向量指针为空,需要重新构建,不会复原被删权重结果。当前 API 启动会拒绝旧 Schema。
|
||||
|
||||
默认测试用明确的三维坐标 fixture 验证 SQL 数学、空间隔离、并发与回滚,绝不代表实际模型质量。真实模型贯通用例显式启用,在独立模型环境运行:
|
||||
|
||||
```bash
|
||||
task_vector_root=$(git rev-parse --absolute-git-dir)
|
||||
uv pip install --python "$task_vector_root/embedding-eval-venv/bin/python" \
|
||||
-r backend/requirements-dev.txt pgserver
|
||||
RUN_LOCAL_EMBEDDING_TEST=1 EMBEDDING_CACHE_DIR="$task_vector_root/embedding-model-cache" \
|
||||
"$task_vector_root/embedding-eval-venv/bin/python" -m pytest -q \
|
||||
backend/tests/test_vector_runtime.py
|
||||
```
|
||||
|
||||
该用例用合成测试文字,验证真实 small 的 512 维编码、HTTP 构建/发布/查询、pgvector 持久化及新进程重启后的空间、发布、命中和历史一致;不是领域分数或生产性能实验。Docker 容器、前端浏览器、RRF 和领域验收保持待办。
|
||||
|
||||
实现依据:[pgvector 精确查询与余弦算子](https://github.com/pgvector/pgvector#querying)、[混合维度存储约束](https://github.com/pgvector/pgvector#can-i-store-vectors-with-different-dimensions-in-the-same-column)、[SQLAlchemy 集成](https://github.com/pgvector/pgvector-python#sqlalchemy)。
|
||||
Reference in New Issue
Block a user